From 576655b9266d3b4267270f594ed8c0b49acd121c Mon Sep 17 00:00:00 2001 From: Nicolas Boichat Date: Wed, 26 Feb 2025 18:09:09 +0100 Subject: [PATCH] uucore: format: Fix printing of floating hex exponents MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Floating hex format is supposed to be `[-]0xh.hhhp±d`. Note that the exponent is a decimal value, not an hex number: fix that. Also, add basic tests for this format, while we're at it. Test: `cargo test --package uucore --all-features float` Fixes #7362. --- .../src/lib/features/format/num_format.rs | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/uucore/src/lib/features/format/num_format.rs b/src/uucore/src/lib/features/format/num_format.rs index caee8e303..361b4de3f 100644 --- a/src/uucore/src/lib/features/format/num_format.rs +++ b/src/uucore/src/lib/features/format/num_format.rs @@ -476,9 +476,9 @@ fn format_float_hexadecimal( }; let mut s = match (precision, force_decimal) { - (0, ForceDecimal::No) => format!("0x{first_digit}p{exponent:+x}"), - (0, ForceDecimal::Yes) => format!("0x{first_digit}.p{exponent:+x}"), - _ => format!("0x{first_digit}.{mantissa:0>13x}p{exponent:+x}"), + (0, ForceDecimal::No) => format!("0x{first_digit}p{exponent:+}"), + (0, ForceDecimal::Yes) => format!("0x{first_digit}.p{exponent:+}"), + _ => format!("0x{first_digit}.{mantissa:0>13x}p{exponent:+}"), }; if case == Case::Uppercase { @@ -654,6 +654,25 @@ mod test { assert_eq!(f(99_999_999.0), "1.e+08"); } + #[test] + fn hexadecimal_float() { + use super::format_float_hexadecimal; + let f = |x| format_float_hexadecimal(x, 6, Case::Lowercase, ForceDecimal::No); + // TODO(#7364): These values do not match coreutils output, but are possible correct representations. + assert_eq!(f(0.00001), "0x1.4f8b588e368f1p-17"); + assert_eq!(f(0.125), "0x1.0000000000000p-3"); + assert_eq!(f(256.0), "0x1.0000000000000p+8"); + assert_eq!(f(65536.0), "0x1.0000000000000p+16"); + + let f = |x| format_float_hexadecimal(x, 0, Case::Lowercase, ForceDecimal::No); + assert_eq!(f(0.125), "0x1p-3"); + assert_eq!(f(256.0), "0x1p+8"); + + let f = |x| format_float_hexadecimal(x, 0, Case::Lowercase, ForceDecimal::Yes); + assert_eq!(f(0.125), "0x1.p-3"); + assert_eq!(f(256.0), "0x1.p+8"); + } + #[test] fn strip_insignificant_end() { use super::strip_fractional_zeroes_and_dot;