Skip to content

Commit

Permalink
Make Display for Decimal more human-friendly
Browse files Browse the repository at this point in the history
  • Loading branch information
jobarr-amzn committed Mar 10, 2023
1 parent e3f7bd1 commit 97f63ac
Showing 1 changed file with 40 additions and 8 deletions.
48 changes: 40 additions & 8 deletions src/types/decimal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,8 +296,37 @@ impl TryFrom<f64> for Decimal {

impl Display for Decimal {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
// TODO: This is correct, but not the most human-friendly format.
write!(f, "{}d{}", self.coefficient, self.exponent)
let digits = &*self.coefficient.magnitude.to_string();
let len = digits.len();
// The index of the decimal
let i_d = len as i64 + self.exponent;

if self.coefficient.sign == Sign::Negative {
write!(f, "-").unwrap();
};

if self.exponent > 6 {
// e.g. A.BCd12
write!(f, "{}.{}d{}", &digits[0..1], &digits[1..len], (i_d - 1))
} else if self.exponent > 0 {
// e.g. ABC0000. or ABC.
let zeroes = "0".repeat(self.exponent as usize);
write!(f, "{}{}.", &digits, &*zeroes)
} else {
// implies a fractional component
if i_d > 0 {
// e.g. A.BC or AB.C
let ui_d = i_d as usize;
write!(f, "{}.{}", &digits[0..ui_d], &digits[ui_d..len])
} else if i_d > -6 {
// e.g. 0.ABC or 0.000ABC
let zeroes = "0".repeat(i_d.abs() as usize);
write!(f, "0.{}{}", &*zeroes, &digits)
} else {
// e.g. A.BCd-12
write!(f, "{}.{}d{}", &digits[0..1], &digits[1..len], (i_d - 1))
}
}
}
}

Expand Down Expand Up @@ -347,12 +376,15 @@ mod decimal_tests {
use rstest::*;

#[rstest]
#[case(Decimal::new(1, 0), "1d0")]
#[case(Decimal::new(123, -2), "123d-2")]
#[case(Decimal::new(123, 2), "123d2")]
#[case(Decimal::negative_zero_with_exponent(0), "-0d0")]
#[case(Decimal::negative_zero_with_exponent(-4), "-0d-4")]
#[case(Decimal::negative_zero_with_exponent(4), "-0d4")]
#[case(Decimal::new(123, 7), "1.23d9")]
#[case(Decimal::new(123, 0), "123.")]
#[case(Decimal::new(-123, 0),"-123.")]
#[case(Decimal::new( 123, -1), "12.3")]
#[case(Decimal::new( 123, -3), "0.123")]
#[case(Decimal::new(-123, -5), "-0.00123")]
#[case(Decimal::new( 123, -5), "0.00123")]
#[case(Decimal::new( 123, -10), "1.23d-8")]
#[case(Decimal::new(-123, -10), "-1.23d-8")]
fn test_display(#[case] decimal: Decimal, #[case] expected: &str) {
let mut buffer = String::new();
write!(buffer, "{decimal}").unwrap();
Expand Down

0 comments on commit 97f63ac

Please sign in to comment.