1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 19:47:45 +00:00

uucore: format: Fix printing of negative floating hex

Negative numbers were not printed correctly with `%a`:
 - A leading `-` is expected.
 - The exponent mask was too wide (15 bits instead of 11)
This commit is contained in:
Nicolas Boichat 2025-02-26 21:42:21 +01:00
parent 576655b926
commit f23e6f1cab

View file

@ -465,20 +465,21 @@ fn format_float_hexadecimal(
case: Case, case: Case,
force_decimal: ForceDecimal, force_decimal: ForceDecimal,
) -> String { ) -> String {
let (first_digit, mantissa, exponent) = if f == 0.0 { let (sign, first_digit, mantissa, exponent) = if f == 0.0 {
(0, 0, 0) ("", 0, 0, 0)
} else { } else {
let bits = f.to_bits(); let bits = f.to_bits();
let exponent_bits = ((bits >> 52) & 0x7fff) as i64; let sign = if (bits >> 63) == 1 { "-" } else { "" };
let exponent_bits = ((bits >> 52) & 0x7ff) as i64;
let exponent = exponent_bits - 1023; let exponent = exponent_bits - 1023;
let mantissa = bits & 0xf_ffff_ffff_ffff; let mantissa = bits & 0xf_ffff_ffff_ffff;
(1, mantissa, exponent) (sign, 1, mantissa, exponent)
}; };
let mut s = match (precision, force_decimal) { let mut s = match (precision, force_decimal) {
(0, ForceDecimal::No) => format!("0x{first_digit}p{exponent:+}"), (0, ForceDecimal::No) => format!("{sign}0x{first_digit}p{exponent:+}"),
(0, ForceDecimal::Yes) => format!("0x{first_digit}.p{exponent:+}"), (0, ForceDecimal::Yes) => format!("{sign}0x{first_digit}.p{exponent:+}"),
_ => format!("0x{first_digit}.{mantissa:0>13x}p{exponent:+}"), _ => format!("{sign}0x{first_digit}.{mantissa:0>13x}p{exponent:+}"),
}; };
if case == Case::Uppercase { if case == Case::Uppercase {
@ -663,14 +664,22 @@ mod test {
assert_eq!(f(0.125), "0x1.0000000000000p-3"); assert_eq!(f(0.125), "0x1.0000000000000p-3");
assert_eq!(f(256.0), "0x1.0000000000000p+8"); assert_eq!(f(256.0), "0x1.0000000000000p+8");
assert_eq!(f(65536.0), "0x1.0000000000000p+16"); assert_eq!(f(65536.0), "0x1.0000000000000p+16");
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); let f = |x| format_float_hexadecimal(x, 0, Case::Lowercase, ForceDecimal::No);
assert_eq!(f(0.125), "0x1p-3"); assert_eq!(f(0.125), "0x1p-3");
assert_eq!(f(256.0), "0x1p+8"); assert_eq!(f(256.0), "0x1p+8");
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); let f = |x| format_float_hexadecimal(x, 0, Case::Lowercase, ForceDecimal::Yes);
assert_eq!(f(0.125), "0x1.p-3"); assert_eq!(f(0.125), "0x1.p-3");
assert_eq!(f(256.0), "0x1.p+8"); assert_eq!(f(256.0), "0x1.p+8");
assert_eq!(f(-0.125), "-0x1.p-3");
assert_eq!(f(-256.0), "-0x1.p+8");
} }
#[test] #[test]