From 7d3a3475b2e812892d6e376ca6909b26c2c1860b Mon Sep 17 00:00:00 2001 From: hayato0909 Date: Mon, 27 Apr 2026 22:14:30 +0900 Subject: [PATCH] numfmt: fix rounding for small scaled values --- src/uu/numfmt/src/format.rs | 7 +++++- tests/by-util/test_numfmt.rs | 44 +++++++++++++++++++++++++++++++++++- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/uu/numfmt/src/format.rs b/src/uu/numfmt/src/format.rs index fee0cca08..372225abe 100644 --- a/src/uu/numfmt/src/format.rs +++ b/src/uu/numfmt/src/format.rs @@ -592,10 +592,15 @@ fn transform_to( } }; Ok(match s { - None => localize(format!( + None if opts.to == Unit::None => localize(format!( "{:.precision$}", round_with_precision(i2, round_method, precision), )), + None if is_precision_specified => { + let i2 = round_with_precision(i2, round_method, 0); + localize(format!("{i2:.precision$}")) + } + None => localize(format!("{i2:.0}")), Some(s) if precision > 0 => localize(format!( "{i2:.precision$}{unit_separator}{}", DisplayableSuffix(s, opts.to), diff --git a/tests/by-util/test_numfmt.rs b/tests/by-util/test_numfmt.rs index b58fa79c6..43566bb36 100644 --- a/tests/by-util/test_numfmt.rs +++ b/tests/by-util/test_numfmt.rs @@ -2,7 +2,8 @@ // // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. -// spell-checker:ignore (paths) gnutest ronna quetta + +// spell-checker:ignore (paths) gnutest ronna quetta unitless use uutests::new_ucmd; @@ -633,6 +634,16 @@ fn test_round() { } } +#[test] +fn test_to_unitless_small_values_use_display_rounding() { + new_ucmd!() + .args(&[ + "--to=si", "--", "0.4", "0.5", "0.6", "1.4", "3.14", "-0.4", "-0.5", "-0.6", "-1.4", + ]) + .succeeds() + .stdout_only("0\n0\n1\n1\n3\n-0\n-0\n-1\n-1\n"); +} + #[test] fn test_round_with_to_unit() { for (method, exp) in [ @@ -659,6 +670,24 @@ fn test_round_with_to_unit() { } } +#[test] +fn test_to_unit_with_unitless_small_value_uses_display_rounding() { + new_ucmd!() + .args(&["--to=iec", "--to-unit=689", "701"]) + .succeeds() + .stdout_only("1\n"); + + new_ucmd!() + .args(&["--to=si", "--to-unit=689", "701"]) + .succeeds() + .stdout_only("1\n"); + + new_ucmd!() + .args(&["--to=none", "--to-unit=689", "701"]) + .succeeds() + .stdout_only("2\n"); +} + #[test] fn test_suffix_is_added_if_not_supplied() { new_ucmd!() @@ -1024,6 +1053,19 @@ fn test_format_with_precision_and_to_arg() { } } +#[test] +fn test_format_with_precision_and_unitless_to_arg() { + new_ucmd!() + .args(&["--to=si", "--format=%.1f", "3.14"]) + .succeeds() + .stdout_is("4.0\n"); + + new_ucmd!() + .args(&["--to=si", "--format=%.1f", "--round=down", "3.14"]) + .succeeds() + .stdout_is("3.0\n"); +} + #[test] fn test_format_preserve_trailing_zeros_if_no_precision_is_specified() { let values = vec!["10.0", "0.0100"];