Apparent F#/BCL floating point bug

前端 未结 3 1714
清酒与你
清酒与你 2021-01-21 11:17

The following is in FSI:

> System.Math.Round(0.2916, 2);;
val it : float = 0.29
> it * 100.;;
val it : float = 29.0
> int it;;
val it : int = 28
         


        
相关标签:
3条回答
  • 2021-01-21 11:31

    This is just how floating point numbers work. The number that appears as 29 in the output is actually slightly smaller than 29 (because floating point numbers are not precise):

    > (System.Math.Round(0.2916, 2) * 100.0) - 29.0;;
    val it : float = -3.552713679e-15
    
    0 讨论(0)
  • 2021-01-21 11:34

    float is binary floating point data type. Not all decimal floating point values can be represented exactly as binary floating point. What FSI shows as 29 is actually 28.999999999999996.

    If you want to store precise decimal floating point values, use decimal data type (to make a number literal decimal instead of float add m to it - e.g. 0.2916m).

    > System.Math.Round(0.2916m, 2);;
    val it : decimal = 0.29M
    > it * 100m;;
    val it : decimal = 29.00M
    > int it;;
    val it : int = 29
    
    0 讨论(0)
  • 2021-01-21 11:46

    You can change the F# FSI Pretty Printer like Matlab "format long"

    fsi.AddPrinter( fun (x:float) -> sprintf "%26.16e" x);;
    

    FSI output

    System.Math.Round( 0.2916, 2)   //  2.8999999999999998e-001
    
    1./3.                           // 3.3333333333333331e-001
    
    0 讨论(0)
提交回复
热议问题