1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-29 12:07:46 +00:00

uucore: format: Workaround BigDecimal printing bug with 0

This is a bigdecimal issue, see
https://github.com/akubera/bigdecimal-rs/issues/144 .

Also add a few tests, including a disabled one (our workaround
is _before_ the call to format_float_decimal).
This commit is contained in:
Nicolas Boichat 2025-03-20 14:35:05 +01:00
parent 35a923b076
commit afbab45350

View file

@ -2,7 +2,7 @@
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
// spell-checker:ignore bigdecimal prec
// spell-checker:ignore bigdecimal prec cppreference
//! Utilities for formatting numbers in various formats
use bigdecimal::BigDecimal;
@ -244,7 +244,13 @@ impl Formatter<&ExtendedBigDecimal> for Float {
*/
let (abs, negative) = match e {
ExtendedBigDecimal::BigDecimal(bd) => {
(ExtendedBigDecimal::BigDecimal(bd.abs()), bd.is_negative())
// Workaround printing bug in BigDecimal, force 0 to scale 0.
// TODO: Remove after https://github.com/akubera/bigdecimal-rs/issues/144 is fixed.
if bd.is_zero() {
(ExtendedBigDecimal::zero(), false)
} else {
(ExtendedBigDecimal::BigDecimal(bd.abs()), bd.is_negative())
}
}
ExtendedBigDecimal::MinusZero => (ExtendedBigDecimal::zero(), true),
ExtendedBigDecimal::Infinity => (ExtendedBigDecimal::Infinity, false),
@ -719,6 +725,21 @@ mod test {
);
}
#[test]
#[ignore = "Need https://github.com/akubera/bigdecimal-rs/issues/144 to be fixed"]
fn decimal_float_zero() {
use super::format_float_decimal;
// We've had issues with "0e10"/"0e-10" formatting.
// TODO: Enable after https://github.com/akubera/bigdecimal-rs/issues/144 is fixed,
// as our workaround is in .fmt.
let f = |digits, scale| {
format_float_decimal(&BigDecimal::from_bigint(digits, scale), 6, ForceDecimal::No)
};
assert_eq!(f(0.into(), 0), "0.000000");
assert_eq!(f(0.into(), -10), "0.000000");
assert_eq!(f(0.into(), 10), "0.000000");
}
#[test]
fn scientific_float() {
use super::format_float_scientific;
@ -748,6 +769,19 @@ mod test {
};
assert_eq!(f(0.0), "0.000000E+00");
assert_eq!(f(123_456.789), "1.234568E+05");
// Test "0e10"/"0e-10". From cppreference.com: "If the value is 0, the exponent is also 0."
let f = |digits, scale| {
format_float_scientific(
&BigDecimal::from_bigint(digits, scale),
6,
Case::Lowercase,
ForceDecimal::No,
)
};
assert_eq!(f(0.into(), 0), "0.000000e+00");
assert_eq!(f(0.into(), -10), "0.000000e+00");
assert_eq!(f(0.into(), 10), "0.000000e+00");
}
#[test]
@ -928,6 +962,19 @@ mod test {
};
assert_eq!(f("0.00001"), "0xA.7C5AC4P-20");
assert_eq!(f("0.125"), "0x8.000000P-6");
// Test "0e10"/"0e-10". From cppreference.com: "If the value is 0, the exponent is also 0."
let f = |digits, scale| {
format_float_hexadecimal(
&BigDecimal::from_bigint(digits, scale),
6,
Case::Lowercase,
ForceDecimal::No,
)
};
assert_eq!(f(0.into(), 0), "0x0.000000p+0");
assert_eq!(f(0.into(), -10), "0x0.000000p+0");
assert_eq!(f(0.into(), 10), "0x0.000000p+0");
}
#[test]