diff --git a/src/uu/numfmt/src/format.rs b/src/uu/numfmt/src/format.rs index 2196a865fb6..155e8b80b7f 100644 --- a/src/uu/numfmt/src/format.rs +++ b/src/uu/numfmt/src/format.rs @@ -735,10 +735,12 @@ fn transform_to( } }; Ok(match s { - None if opts.to == Unit::None && precision <= u16::MAX.into() => localize(format_float( - round_with_precision(i2, round_method, precision), - precision, - )), + None if opts.to == Unit::None && precision <= u16::MAX.into() => { + let rounded = round_with_precision(i2, round_method, precision); + // rounding a small negative number leaves -0.0, which would print as "-0" + let rounded = if rounded == 0.0 { 0.0 } else { rounded }; + localize(format_float(rounded, precision)) + } None if is_precision_specified && precision <= u16::MAX.into() => { let i2 = round_with_precision(i2, round_method, 0); localize(format_float(i2, precision)) diff --git a/tests/by-util/test_numfmt.rs b/tests/by-util/test_numfmt.rs index 822f498180f..036da1c09cc 100644 --- a/tests/by-util/test_numfmt.rs +++ b/tests/by-util/test_numfmt.rs @@ -254,6 +254,16 @@ fn test_negative_zero() { .stdout_is("0\n0.0"); } +// A negative number that rounds to zero prints an unsigned zero. +#[rstest] +#[case::round_up_format_precision(&["--round=up", "--format=%.0f", "--", "-0.3"], "0\n")] +#[case::to_unit_round_nearest(&["--to-unit=10", "--round=nearest", "--", "-3"], "0\n")] +#[case::zero_padded(&["--round=up", "--format=%05.0f", "--", "-0.3"], "00000\n")] +#[case::fractional_precision(&["--round=nearest", "--format=%.1f", "--", "-0.04"], "0.0\n")] +fn test_negative_number_rounded_to_zero(#[case] args: &[&str], #[case] expected: &str) { + new_ucmd!().args(args).succeeds().stdout_only(expected); +} + #[test] fn test_no_op() { new_ucmd!()