Skip to content

Commit 796b9ce

Browse files
authored
Merge pull request akubera#66 from pymongo/master
Add round implementation
2 parents 13a732f + 7423494 commit 796b9ce

File tree

1 file changed

+54
-0
lines changed

1 file changed

+54
-0
lines changed

src/lib.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,32 @@ impl BigDecimal {
582582
return result;
583583
}
584584

585+
/// Return number rounded to round_digits precision after the decimal point
586+
fn round(&self, round_digits: i64) -> BigDecimal {
587+
let (bigint, decimal_part_digits) = self.as_bigint_and_exponent();
588+
let need_to_round_digits = decimal_part_digits - round_digits;
589+
if round_digits >= 0 && need_to_round_digits <= 0 {
590+
return self.clone();
591+
}
592+
593+
let mut number = bigint.to_i128().unwrap();
594+
if number < 0 {
595+
number = -number;
596+
}
597+
for _ in 0..(need_to_round_digits - 1) {
598+
number /= 10;
599+
}
600+
let digit = number % 10;
601+
602+
if digit <= 4 {
603+
self.with_scale(round_digits)
604+
} else if bigint.is_negative() {
605+
self.with_scale(round_digits) - BigDecimal::new(BigInt::from(1), round_digits)
606+
} else {
607+
self.with_scale(round_digits) + BigDecimal::new(BigInt::from(1), round_digits)
608+
}
609+
}
610+
585611
/// Return true if this number has zero fractional part (is equal
586612
/// to an integer)
587613
///
@@ -2549,6 +2575,34 @@ mod bigdecimal_tests {
25492575
}
25502576
}
25512577

2578+
#[test]
2579+
fn test_round() {
2580+
let test_cases = vec![
2581+
("1.45", 1, "1.5"),
2582+
("1.444445", 1, "1.4"),
2583+
("1.44", 1, "1.4"),
2584+
("0.444", 2, "0.44"),
2585+
("0.0045", 2, "0.00"),
2586+
("-1.555", 2, "-1.56"),
2587+
("-1.555", 99, "-1.555"),
2588+
("5.5", 0, "6"),
2589+
("-1", -1, "0"),
2590+
("5", -1, "10"),
2591+
("44", -1, "40"),
2592+
("44", -99, "0"),
2593+
("1.4499999999", 1, "1.4"),
2594+
("-1.4499999999", 1, "-1.4"),
2595+
("1.449999999", 1, "1.4"),
2596+
("-9999.444455556666", 10, "-9999.4444555567"),
2597+
("-12345678987654321.123456789", 8, "-12345678987654321.12345679"),
2598+
];
2599+
for &(x, digits, y) in test_cases.iter() {
2600+
let a = BigDecimal::from_str(x).unwrap();
2601+
let b = BigDecimal::from_str(y).unwrap();
2602+
assert_eq!(a.round(digits), b);
2603+
}
2604+
}
2605+
25522606
#[test]
25532607
fn test_is_integer() {
25542608
let true_vals = vec![

0 commit comments

Comments
 (0)