@@ -582,6 +582,32 @@ impl BigDecimal {
582
582
return result;
583
583
}
584
584
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
+
585
611
/// Return true if this number has zero fractional part (is equal
586
612
/// to an integer)
587
613
///
@@ -2549,6 +2575,34 @@ mod bigdecimal_tests {
2549
2575
}
2550
2576
}
2551
2577
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
+
2552
2606
#[ test]
2553
2607
fn test_is_integer ( ) {
2554
2608
let true_vals = vec ! [
0 commit comments