@@ -581,6 +581,35 @@ impl BigDecimal {
581
581
return result;
582
582
}
583
583
584
+ /// Return number rounded to round_digits precision after the decimal point
585
+ /// panic if self.digits() > 16
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_i64 ( ) . unwrap ( ) ;
594
+ // avoid -1555 / 10 = -156
595
+ if number < 0 {
596
+ number = -number;
597
+ }
598
+ for _ in 0 ..( need_to_round_digits-1 ) {
599
+ number /= 10 ;
600
+ }
601
+ let digit = number % 10 ;
602
+ if digit <= 4 {
603
+ self . with_scale ( round_digits)
604
+ } else {
605
+ if bigint. sign ( ) == Sign :: Minus {
606
+ self . with_scale ( round_digits) - BigDecimal :: new ( BigInt :: from ( 1 ) , round_digits)
607
+ } else {
608
+ self . with_scale ( round_digits) + BigDecimal :: new ( BigInt :: from ( 1 ) , round_digits)
609
+ }
610
+ }
611
+ }
612
+
584
613
/// Return true if this number has zero fractional part (is equal
585
614
/// to an integer)
586
615
///
@@ -2535,6 +2564,33 @@ mod bigdecimal_tests {
2535
2564
}
2536
2565
}
2537
2566
2567
+ #[ test]
2568
+ fn test_round ( ) {
2569
+ let test_cases = vec ! [
2570
+ ( "1.45" , 1 , "1.5" ) ,
2571
+ ( "1.444445" , 1 , "1.4" ) ,
2572
+ ( "1.44" , 1 , "1.4" ) ,
2573
+ ( "0.444" , 2 , "0.44" ) ,
2574
+ ( "0.0045" , 2 , "0.00" ) ,
2575
+ ( "-1.555" , 2 , "-1.56" ) ,
2576
+ ( "-1.555" , 99 , "-1.555" ) ,
2577
+ ( "5.5" , 0 , "6" ) ,
2578
+ ( "-1" , -1 , "0" ) ,
2579
+ ( "5" , -1 , "10" ) ,
2580
+ ( "44" , -1 , "40" ) ,
2581
+ ( "44" , -99 , "0" ) ,
2582
+ ( "1.4499999999" , 1 , "1.4" ) ,
2583
+ ( "-1.4499999999" , 1 , "-1.4" ) ,
2584
+ ( "1.449999999" , 1 , "1.4" ) ,
2585
+ ( "-9999.444455556666" , 10 , "-9999.4444555567" ) ,
2586
+ ] ;
2587
+ for & ( x, digits, y) in test_cases. iter ( ) {
2588
+ let a = BigDecimal :: from_str ( x) . unwrap ( ) ;
2589
+ let b = BigDecimal :: from_str ( y) . unwrap ( ) ;
2590
+ assert_eq ! ( a. round( digits) , b) ;
2591
+ }
2592
+ }
2593
+
2538
2594
#[ test]
2539
2595
fn test_is_integer ( ) {
2540
2596
let true_vals = vec ! [
0 commit comments