Skip to content

Commit

Permalink
Fixes issue with mantissa sf calculation (#434)
Browse files Browse the repository at this point in the history
  • Loading branch information
paupino committed Oct 15, 2021
1 parent c74bd40 commit 67c29ef
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 2 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ Documentation detailing the additional functions can be found on the

Please note that `ln` and `log10` will panic on invalid input with `checked_ln` and `checked_log10` the preferred functions
to curb against this. When the `maths` feature was first developed the library would return `0` on invalid input. To re-enable this
non-panicing behavior, please use the feature: `maths-nopanic`.
non-panicking behavior, please use the feature: `maths-nopanic`.

### `rust-fuzz`

Expand Down
7 changes: 7 additions & 0 deletions VERSION.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Version History

## Unreleased

* Fixes panic when display precision was specified greater than 30. [#428](https://github.com/paupino/rust-decimal/issues/428).
* Binds `deserialize` so that invalid scale values cannot be set. This may be a breaking change for some users leveraging
this in a `const` function. [#428](https://github.com/paupino/rust-decimal/issues/428).
* Fixes an issue in `round_sf` whereby integral values that started with a 1 would output incorrect rounded numbers. [#430](https://github.com/paupino/rust-decimal/issues/430).

## 1.16.0

* Implement `sin`/`cos`/`tan` functions which are enabled within the `maths` feature. [#413](https://github.com/paupino/rust-decimal/pull/413).
Expand Down
5 changes: 4 additions & 1 deletion src/decimal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1256,6 +1256,7 @@ impl Decimal {
let _remainder = ops::array::div_by_u32(&mut working, 10u32);
mantissa_sf += 1;
if working[2] == 0 && working[1] == 0 && working[0] == 1 {
mantissa_sf += 1;
break;
}
}
Expand Down Expand Up @@ -1287,8 +1288,10 @@ impl Decimal {
use crate::constants::BIG_POWERS_10;
// We need to adjust the integral portion. This also should be rounded, consequently
// we reduce the number down, round it, and then scale back up.
// E.g. If we have 305.459 scaling to a sf of 2. We first, reduce the number
// E.g. If we have 305.459 scaling to a sf of 2 - we first reduce the number
// down to 30.5459, round it to 31 and then scale it back up to 310.
// Likewise, if we have 12301 scaling to a sf of 3 - we first reduce the number
// down to 123.01, round it to 123 and then scale it back up to 12300.
let mut num = *self;
let mut exp = (diff - scale) as usize;
while exp > 0 {
Expand Down
39 changes: 39 additions & 0 deletions tests/decimal_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2413,6 +2413,45 @@ fn it_can_round_significant_figures() {
}
}

#[test]
fn it_can_round_significant_figures_with_strategy() {
let tests = &[
("12301", 3u32, RoundingStrategy::AwayFromZero, Some("12400")),
("123.01", 3u32, RoundingStrategy::AwayFromZero, Some("124")),
("1.2301", 3u32, RoundingStrategy::AwayFromZero, Some("1.24")),
("0.12301", 3u32, RoundingStrategy::AwayFromZero, Some("0.124")),
];
for &(input, sf, strategy, expected) in tests {
let input = Decimal::from_str(input).unwrap();
let result = input.round_sf_with_strategy(sf, strategy);
if let Some(expected) = expected {
assert!(
result.is_some(),
"Expected result for {}.round_sf_with_strategy({}, {:?})",
input,
sf,
strategy
);
assert_eq!(
expected,
result.unwrap().to_string(),
"{}.round_sf_with_strategy({}, {:?})",
input,
sf,
strategy
);
} else {
assert!(
result.is_none(),
"Unexpected result for {}.round_sf_with_strategy({}, {:?})",
input,
sf,
strategy
);
}
}
}

#[test]
fn it_can_trunc() {
let tests = &[("1.00000000000000000000", "1"), ("1.000000000000000000000001", "1")];
Expand Down

0 comments on commit 67c29ef

Please sign in to comment.