@@ -1391,7 +1391,12 @@ macro_rules! to_primitive_small {
1391
1391
}
1392
1392
1393
1393
fn to_f64( & self ) -> Option <f64 > {
1394
- Some ( self . numer. to_f64( ) . unwrap( ) / self . denom. to_f64( ) . unwrap( ) )
1394
+ let float = self . numer. to_f64( ) . unwrap( ) / self . denom. to_f64( ) . unwrap( ) ;
1395
+ if float. is_nan( ) {
1396
+ None
1397
+ } else {
1398
+ Some ( float)
1399
+ }
1395
1400
}
1396
1401
}
1397
1402
) * )
@@ -1424,10 +1429,15 @@ macro_rules! to_primitive_64 {
1424
1429
}
1425
1430
1426
1431
fn to_f64( & self ) -> Option <f64 > {
1427
- Some ( ratio_to_f64(
1432
+ let float = ratio_to_f64(
1428
1433
self . numer as i128 ,
1429
1434
self . denom as i128
1430
- ) )
1435
+ ) ;
1436
+ if float. is_nan( ) {
1437
+ None
1438
+ } else {
1439
+ Some ( float)
1440
+ }
1431
1441
}
1432
1442
}
1433
1443
) * )
@@ -1458,16 +1468,21 @@ impl<T: Clone + Integer + ToPrimitive + ToBigInt> ToPrimitive for Ratio<T> {
1458
1468
}
1459
1469
1460
1470
fn to_f64 ( & self ) -> Option < f64 > {
1461
- match ( self . numer . to_i64 ( ) , self . denom . to_i64 ( ) ) {
1462
- ( Some ( numer) , Some ( denom) ) => Some ( ratio_to_f64 (
1471
+ let float = match ( self . numer . to_i64 ( ) , self . denom . to_i64 ( ) ) {
1472
+ ( Some ( numer) , Some ( denom) ) => ratio_to_f64 (
1463
1473
<i128 as From < _ > >:: from ( numer) ,
1464
1474
<i128 as From < _ > >:: from ( denom) ,
1465
- ) ) ,
1475
+ ) ,
1466
1476
_ => {
1467
1477
let numer: BigInt = self . numer . to_bigint ( ) ?;
1468
1478
let denom: BigInt = self . denom . to_bigint ( ) ?;
1469
- Some ( ratio_to_f64 ( numer, denom) )
1479
+ ratio_to_f64 ( numer, denom)
1470
1480
}
1481
+ } ;
1482
+ if float. is_nan ( ) {
1483
+ None
1484
+ } else {
1485
+ Some ( float)
1471
1486
}
1472
1487
}
1473
1488
}
@@ -1507,10 +1522,9 @@ fn ratio_to_f64<T: Bits + Clone + Integer + Signed + ShlAssign<usize> + ToPrimit
1507
1522
const MAX_EXACT_INT : i64 = 1i64 << core:: f64:: MANTISSA_DIGITS ;
1508
1523
const MIN_EXACT_INT : i64 = -MAX_EXACT_INT ;
1509
1524
1510
- let flo_sign = numer. signum ( ) . to_f64 ( ) . unwrap ( ) * denom. signum ( ) . to_f64 ( ) . unwrap ( ) ;
1511
-
1512
- if numer. is_zero ( ) {
1513
- return 0.0 * flo_sign;
1525
+ let flo_sign = numer. signum ( ) . to_f64 ( ) . unwrap ( ) / denom. signum ( ) . to_f64 ( ) . unwrap ( ) ;
1526
+ if !flo_sign. is_normal ( ) {
1527
+ return flo_sign;
1514
1528
}
1515
1529
1516
1530
// Fast track: both sides can losslessly be converted to f64s. In this case, letting the
@@ -2899,47 +2913,67 @@ mod test {
2899
2913
. unwrap( ) ,
2900
2914
"3" . parse( ) . unwrap( )
2901
2915
)
2902
- . to_f64( )
2903
- . unwrap( ) ,
2904
- 411522630329218100000000000000000000000000000f64
2916
+ . to_f64( ) ,
2917
+ Some ( 411522630329218100000000000000000000000000000f64 )
2918
+ ) ;
2919
+ assert_eq ! (
2920
+ BigRational :: new( BigInt :: one( ) , BigInt :: one( ) << 1050 ) . to_f64( ) ,
2921
+ Some ( 0f64 )
2905
2922
) ;
2906
2923
assert_eq ! (
2907
- BigRational :: new( 1 . into( ) , BigInt :: one( ) << 1050 , )
2908
- . to_f64( )
2909
- . unwrap( ) ,
2910
- 0f64
2924
+ BigRational :: from( BigInt :: one( ) << 1050 ) . to_f64( ) ,
2925
+ Some ( core:: f64 :: INFINITY )
2926
+ ) ;
2927
+ assert_eq ! (
2928
+ BigRational :: from( ( -BigInt :: one( ) ) << 1050 ) . to_f64( ) ,
2929
+ Some ( core:: f64 :: NEG_INFINITY )
2911
2930
) ;
2912
2931
assert_eq ! (
2913
2932
BigRational :: new(
2914
2933
"1234567890987654321234567890" . parse( ) . unwrap( ) ,
2915
2934
"987654321234567890987654321" . parse( ) . unwrap( )
2916
2935
)
2917
- . to_f64( )
2918
- . unwrap( ) ,
2919
- 1.2499999893125f64
2936
+ . to_f64( ) ,
2937
+ Some ( 1.2499999893125f64 )
2938
+ ) ;
2939
+ assert_eq ! (
2940
+ BigRational :: new_raw( BigInt :: one( ) , BigInt :: zero( ) ) . to_f64( ) ,
2941
+ Some ( core:: f64 :: INFINITY )
2942
+ ) ;
2943
+ assert_eq ! (
2944
+ BigRational :: new_raw( -BigInt :: one( ) , BigInt :: zero( ) ) . to_f64( ) ,
2945
+ Some ( core:: f64 :: NEG_INFINITY )
2946
+ ) ;
2947
+ assert_eq ! (
2948
+ BigRational :: new_raw( BigInt :: zero( ) , BigInt :: zero( ) ) . to_f64( ) ,
2949
+ None
2920
2950
) ;
2921
2951
}
2922
2952
2923
2953
#[ test]
2924
2954
fn test_ratio_to_f64 ( ) {
2925
- assert_eq ! ( 0.5f64 , Ratio :: <u8 >:: new( 1 , 2 ) . to_f64( ) . unwrap( ) ) ;
2926
- assert_eq ! ( 0.5f64 , Rational64 :: new( 1 , 2 ) . to_f64( ) . unwrap( ) ) ;
2927
- assert_eq ! ( -0.5f64 , Rational64 :: new( 1 , -2 ) . to_f64( ) . unwrap( ) ) ;
2928
- assert_eq ! ( 0.0f64 , Rational64 :: new( 0 , 2 ) . to_f64( ) . unwrap( ) ) ;
2929
- assert_eq ! ( -0.0f64 , Rational64 :: new( 0 , -2 ) . to_f64( ) . unwrap( ) ) ;
2955
+ assert_eq ! ( Ratio :: <u8 >:: new( 1 , 2 ) . to_f64( ) , Some ( 0.5f64 ) ) ;
2956
+ assert_eq ! ( Rational64 :: new( 1 , 2 ) . to_f64( ) , Some ( 0.5f64 ) ) ;
2957
+ assert_eq ! ( Rational64 :: new( 1 , -2 ) . to_f64( ) , Some ( -0.5f64 ) ) ;
2958
+ assert_eq ! ( Rational64 :: new( 0 , 2 ) . to_f64( ) , Some ( 0.0f64 ) ) ;
2959
+ assert_eq ! ( Rational64 :: new( 0 , -2 ) . to_f64( ) , Some ( -0.0f64 ) ) ;
2960
+ assert_eq ! ( Rational64 :: new( ( 1 << 57 ) + 1 , 1 << 54 ) . to_f64( ) , Some ( 8f64 ) ) ;
2930
2961
assert_eq ! (
2931
- 8f64 ,
2932
- Rational64 :: new ( ( 1 << 57 ) + 1 , 1 << 54 ) . to_f64 ( ) . unwrap ( )
2962
+ Rational64 :: new ( ( 1 << 52 ) + 1 , 1 << 52 ) . to_f64 ( ) ,
2963
+ Some ( 1.0000000000000002f64 ) ,
2933
2964
) ;
2934
2965
assert_eq ! (
2935
- 1.0000000000000002f64 ,
2936
- Rational64 :: new ( ( 1 << 52 ) + 1 , 1 << 52 ) . to_f64 ( ) . unwrap ( )
2966
+ Rational64 :: new ( ( 1 << 60 ) + ( 1 << 8 ) , 1 << 60 ) . to_f64 ( ) ,
2967
+ Some ( 1.0000000000000002f64 ) ,
2937
2968
) ;
2938
2969
assert_eq ! (
2939
- 1.0000000000000002f64 ,
2940
- Rational64 :: new( ( 1 << 60 ) + ( 1 << 8 ) , 1 << 60 )
2941
- . to_f64( )
2942
- . unwrap( )
2970
+ Ratio :: <i32 >:: new_raw( 1 , 0 ) . to_f64( ) ,
2971
+ Some ( core:: f64 :: INFINITY )
2972
+ ) ;
2973
+ assert_eq ! (
2974
+ Ratio :: <i32 >:: new_raw( -1 , 0 ) . to_f64( ) ,
2975
+ Some ( core:: f64 :: NEG_INFINITY )
2943
2976
) ;
2977
+ assert_eq ! ( Ratio :: <i32 >:: new_raw( 0 , 0 ) . to_f64( ) , None ) ;
2944
2978
}
2945
2979
}
0 commit comments