Skip to content

Commit 481cb9f

Browse files
committed
uucore: format: Workaround BigDecimal printing bug with 0
This is a bigdecimal issue, see akubera/bigdecimal-rs#144 . Also add a few tests, including a disabled one (our workaround is _before_ the call to format_float_decimal).
1 parent 105042f commit 481cb9f

File tree

1 file changed

+49
-2
lines changed

1 file changed

+49
-2
lines changed

src/uucore/src/lib/features/format/num_format.rs

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// For the full copyright and license information, please view the LICENSE
44
// file that was distributed with this source code.
5-
// spell-checker:ignore bigdecimal prec
5+
// spell-checker:ignore bigdecimal prec cppreference
66
//! Utilities for formatting numbers in various formats
77
88
use bigdecimal::num_bigint::ToBigInt;
@@ -244,7 +244,13 @@ impl Formatter<&ExtendedBigDecimal> for Float {
244244
*/
245245
let (abs, negative) = match e {
246246
ExtendedBigDecimal::BigDecimal(bd) => {
247-
(ExtendedBigDecimal::BigDecimal(bd.abs()), bd.is_negative())
247+
// Workaround printing bug in BigDecimal, force 0 to scale 0.
248+
// TODO: Remove after https://github.com/akubera/bigdecimal-rs/issues/144 is fixed.
249+
if bd.is_zero() {
250+
(ExtendedBigDecimal::zero(), false)
251+
} else {
252+
(ExtendedBigDecimal::BigDecimal(bd.abs()), bd.is_negative())
253+
}
248254
}
249255
ExtendedBigDecimal::MinusZero => (ExtendedBigDecimal::zero(), true),
250256
ExtendedBigDecimal::Infinity => (ExtendedBigDecimal::Infinity, false),
@@ -719,6 +725,21 @@ mod test {
719725
);
720726
}
721727

728+
#[test]
729+
#[ignore = "Need https://github.com/akubera/bigdecimal-rs/issues/144 to be fixed"]
730+
fn decimal_float_zero() {
731+
use super::format_float_decimal;
732+
// We've had issues with "0e10"/"0e-10" formatting.
733+
// TODO: Enable after https://github.com/akubera/bigdecimal-rs/issues/144 is fixed,
734+
// as our workaround is in .fmt.
735+
let f = |digits, scale| {
736+
format_float_decimal(&BigDecimal::from_bigint(digits, scale), 6, ForceDecimal::No)
737+
};
738+
assert_eq!(f(0.into(), 0), "0.000000");
739+
assert_eq!(f(0.into(), -10), "0.000000");
740+
assert_eq!(f(0.into(), 10), "0.000000");
741+
}
742+
722743
#[test]
723744
fn scientific_float() {
724745
use super::format_float_scientific;
@@ -748,6 +769,19 @@ mod test {
748769
};
749770
assert_eq!(f(0.0), "0.000000E+00");
750771
assert_eq!(f(123_456.789), "1.234568E+05");
772+
773+
// Test "0e10"/"0e-10". From cppreference.com: "If the value is ​0​, the exponent is also ​0​."
774+
let f = |digits, scale| {
775+
format_float_scientific(
776+
&BigDecimal::from_bigint(digits, scale),
777+
6,
778+
Case::Lowercase,
779+
ForceDecimal::No,
780+
)
781+
};
782+
assert_eq!(f(0.into(), 0), "0.000000e+00");
783+
assert_eq!(f(0.into(), -10), "0.000000e+00");
784+
assert_eq!(f(0.into(), 10), "0.000000e+00");
751785
}
752786

753787
#[test]
@@ -928,6 +962,19 @@ mod test {
928962
};
929963
assert_eq!(f("0.00001"), "0xA.7C5AC4P-20");
930964
assert_eq!(f("0.125"), "0x8.000000P-6");
965+
966+
// Test "0e10"/"0e-10". From cppreference.com: "If the value is ​0​, the exponent is also ​0​."
967+
let f = |digits, scale| {
968+
format_float_hexadecimal(
969+
&BigDecimal::from_bigint(digits, scale),
970+
6,
971+
Case::Lowercase,
972+
ForceDecimal::No,
973+
)
974+
};
975+
assert_eq!(f(0.into(), 0), "0x0.000000p+0");
976+
assert_eq!(f(0.into(), -10), "0x0.000000p+0");
977+
assert_eq!(f(0.into(), 10), "0x0.000000p+0");
931978
}
932979

933980
#[test]

0 commit comments

Comments
 (0)