@@ -1382,7 +1382,12 @@ macro_rules! to_primitive_small {
1382
1382
}
1383
1383
1384
1384
fn to_f64( & self ) -> Option <f64 > {
1385
- Some ( self . numer. to_f64( ) . unwrap( ) / self . denom. to_f64( ) . unwrap( ) )
1385
+ let float = self . numer. to_f64( ) . unwrap( ) / self . denom. to_f64( ) . unwrap( ) ;
1386
+ if float. is_nan( ) {
1387
+ None
1388
+ } else {
1389
+ Some ( float)
1390
+ }
1386
1391
}
1387
1392
}
1388
1393
) * )
@@ -1415,10 +1420,15 @@ macro_rules! to_primitive_64 {
1415
1420
}
1416
1421
1417
1422
fn to_f64( & self ) -> Option <f64 > {
1418
- Some ( ratio_to_f64(
1423
+ let float = ratio_to_f64(
1419
1424
self . numer as i128 ,
1420
1425
self . denom as i128
1421
- ) )
1426
+ ) ;
1427
+ if float. is_nan( ) {
1428
+ None
1429
+ } else {
1430
+ Some ( float)
1431
+ }
1422
1432
}
1423
1433
}
1424
1434
) * )
@@ -1449,16 +1459,21 @@ impl<T: Clone + Integer + ToPrimitive + ToBigInt> ToPrimitive for Ratio<T> {
1449
1459
}
1450
1460
1451
1461
fn to_f64 ( & self ) -> Option < f64 > {
1452
- match ( self . numer . to_i64 ( ) , self . denom . to_i64 ( ) ) {
1453
- ( Some ( numer) , Some ( denom) ) => Some ( ratio_to_f64 (
1462
+ let float = match ( self . numer . to_i64 ( ) , self . denom . to_i64 ( ) ) {
1463
+ ( Some ( numer) , Some ( denom) ) => ratio_to_f64 (
1454
1464
<i128 as From < _ > >:: from ( numer) ,
1455
1465
<i128 as From < _ > >:: from ( denom) ,
1456
- ) ) ,
1466
+ ) ,
1457
1467
_ => {
1458
1468
let numer: BigInt = self . numer . to_bigint ( ) ?;
1459
1469
let denom: BigInt = self . denom . to_bigint ( ) ?;
1460
- Some ( ratio_to_f64 ( numer, denom) )
1470
+ ratio_to_f64 ( numer, denom)
1461
1471
}
1472
+ } ;
1473
+ if float. is_nan ( ) {
1474
+ None
1475
+ } else {
1476
+ Some ( float)
1462
1477
}
1463
1478
}
1464
1479
}
@@ -1498,10 +1513,9 @@ fn ratio_to_f64<T: Bits + Clone + Integer + Signed + ShlAssign<usize> + ToPrimit
1498
1513
const MAX_EXACT_INT : i64 = 1i64 << core:: f64:: MANTISSA_DIGITS ;
1499
1514
const MIN_EXACT_INT : i64 = -MAX_EXACT_INT ;
1500
1515
1501
- let flo_sign = numer. signum ( ) . to_f64 ( ) . unwrap ( ) * denom. signum ( ) . to_f64 ( ) . unwrap ( ) ;
1502
-
1503
- if numer. is_zero ( ) {
1504
- return 0.0 * flo_sign;
1516
+ let flo_sign = numer. signum ( ) . to_f64 ( ) . unwrap ( ) / denom. signum ( ) . to_f64 ( ) . unwrap ( ) ;
1517
+ if !flo_sign. is_normal ( ) {
1518
+ return flo_sign;
1505
1519
}
1506
1520
1507
1521
// Fast track: both sides can losslessly be converted to f64s. In this case, letting the
@@ -2890,47 +2904,67 @@ mod test {
2890
2904
. unwrap( ) ,
2891
2905
"3" . parse( ) . unwrap( )
2892
2906
)
2893
- . to_f64( )
2894
- . unwrap( ) ,
2895
- 411522630329218100000000000000000000000000000f64
2907
+ . to_f64( ) ,
2908
+ Some ( 411522630329218100000000000000000000000000000f64 )
2909
+ ) ;
2910
+ assert_eq ! (
2911
+ BigRational :: new( BigInt :: one( ) , BigInt :: one( ) << 1050 ) . to_f64( ) ,
2912
+ Some ( 0f64 )
2896
2913
) ;
2897
2914
assert_eq ! (
2898
- BigRational :: new( 1 . into( ) , BigInt :: one( ) << 1050 , )
2899
- . to_f64( )
2900
- . unwrap( ) ,
2901
- 0f64
2915
+ BigRational :: from( BigInt :: one( ) << 1050 ) . to_f64( ) ,
2916
+ Some ( core:: f64 :: INFINITY )
2917
+ ) ;
2918
+ assert_eq ! (
2919
+ BigRational :: from( ( -BigInt :: one( ) ) << 1050 ) . to_f64( ) ,
2920
+ Some ( core:: f64 :: NEG_INFINITY )
2902
2921
) ;
2903
2922
assert_eq ! (
2904
2923
BigRational :: new(
2905
2924
"1234567890987654321234567890" . parse( ) . unwrap( ) ,
2906
2925
"987654321234567890987654321" . parse( ) . unwrap( )
2907
2926
)
2908
- . to_f64( )
2909
- . unwrap( ) ,
2910
- 1.2499999893125f64
2927
+ . to_f64( ) ,
2928
+ Some ( 1.2499999893125f64 )
2929
+ ) ;
2930
+ assert_eq ! (
2931
+ BigRational :: new_raw( BigInt :: one( ) , BigInt :: zero( ) ) . to_f64( ) ,
2932
+ Some ( core:: f64 :: INFINITY )
2933
+ ) ;
2934
+ assert_eq ! (
2935
+ BigRational :: new_raw( -BigInt :: one( ) , BigInt :: zero( ) ) . to_f64( ) ,
2936
+ Some ( core:: f64 :: NEG_INFINITY )
2937
+ ) ;
2938
+ assert_eq ! (
2939
+ BigRational :: new_raw( BigInt :: zero( ) , BigInt :: zero( ) ) . to_f64( ) ,
2940
+ None
2911
2941
) ;
2912
2942
}
2913
2943
2914
2944
#[ test]
2915
2945
fn test_ratio_to_f64 ( ) {
2916
- assert_eq ! ( 0.5f64 , Ratio :: <u8 >:: new( 1 , 2 ) . to_f64( ) . unwrap( ) ) ;
2917
- assert_eq ! ( 0.5f64 , Rational64 :: new( 1 , 2 ) . to_f64( ) . unwrap( ) ) ;
2918
- assert_eq ! ( -0.5f64 , Rational64 :: new( 1 , -2 ) . to_f64( ) . unwrap( ) ) ;
2919
- assert_eq ! ( 0.0f64 , Rational64 :: new( 0 , 2 ) . to_f64( ) . unwrap( ) ) ;
2920
- assert_eq ! ( -0.0f64 , Rational64 :: new( 0 , -2 ) . to_f64( ) . unwrap( ) ) ;
2946
+ assert_eq ! ( Ratio :: <u8 >:: new( 1 , 2 ) . to_f64( ) , Some ( 0.5f64 ) ) ;
2947
+ assert_eq ! ( Rational64 :: new( 1 , 2 ) . to_f64( ) , Some ( 0.5f64 ) ) ;
2948
+ assert_eq ! ( Rational64 :: new( 1 , -2 ) . to_f64( ) , Some ( -0.5f64 ) ) ;
2949
+ assert_eq ! ( Rational64 :: new( 0 , 2 ) . to_f64( ) , Some ( 0.0f64 ) ) ;
2950
+ assert_eq ! ( Rational64 :: new( 0 , -2 ) . to_f64( ) , Some ( -0.0f64 ) ) ;
2951
+ assert_eq ! ( Rational64 :: new( ( 1 << 57 ) + 1 , 1 << 54 ) . to_f64( ) , Some ( 8f64 ) ) ;
2921
2952
assert_eq ! (
2922
- 8f64 ,
2923
- Rational64 :: new ( ( 1 << 57 ) + 1 , 1 << 54 ) . to_f64 ( ) . unwrap ( )
2953
+ Rational64 :: new ( ( 1 << 52 ) + 1 , 1 << 52 ) . to_f64 ( ) ,
2954
+ Some ( 1.0000000000000002f64 ) ,
2924
2955
) ;
2925
2956
assert_eq ! (
2926
- 1.0000000000000002f64 ,
2927
- Rational64 :: new ( ( 1 << 52 ) + 1 , 1 << 52 ) . to_f64 ( ) . unwrap ( )
2957
+ Rational64 :: new ( ( 1 << 60 ) + ( 1 << 8 ) , 1 << 60 ) . to_f64 ( ) ,
2958
+ Some ( 1.0000000000000002f64 ) ,
2928
2959
) ;
2929
2960
assert_eq ! (
2930
- 1.0000000000000002f64 ,
2931
- Rational64 :: new( ( 1 << 60 ) + ( 1 << 8 ) , 1 << 60 )
2932
- . to_f64( )
2933
- . unwrap( )
2961
+ Ratio :: <i32 >:: new_raw( 1 , 0 ) . to_f64( ) ,
2962
+ Some ( core:: f64 :: INFINITY )
2963
+ ) ;
2964
+ assert_eq ! (
2965
+ Ratio :: <i32 >:: new_raw( -1 , 0 ) . to_f64( ) ,
2966
+ Some ( core:: f64 :: NEG_INFINITY )
2934
2967
) ;
2968
+ assert_eq ! ( Ratio :: <i32 >:: new_raw( 0 , 0 ) . to_f64( ) , None ) ;
2935
2969
}
2936
2970
}
0 commit comments