明显的 F#/BCL 浮点错误
Apparent F#/BCL floating point bug
以下是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
结果在我尝试过的所有地方都是一样的——编译的 F# 3.1/.NET 4.0 应用程序,Visual Studio 2013 和 2015 中的 FSI,.NET Fiddle,@fsibot....
这肯定是某个地方的错误,不是吗?这是怎么回事?
这就是浮点数的工作原理。在输出中显示为 29 的数字实际上比 29 略小(因为浮点数不精确):
> (System.Math.Round(0.2916, 2) * 100.0) - 29.0;;
val it : float = -3.552713679e-15
float
是二进制浮点数据类型。并非所有十进制浮点值都可以精确表示为二进制浮点数。 FSI 显示为 29
实际上是 28.999999999999996
.
如果要存储精确的十进制浮点值,请使用 decimal
数据类型(使数字文字 decimal
而不是 float
添加 m
- 例如 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
您可以像 Matlab 一样更改 F# FSI Pretty Printer "format long"
fsi.AddPrinter( fun (x:float) -> sprintf "%26.16e" x);;
FSI输出
System.Math.Round( 0.2916, 2) // 2.8999999999999998e-001
1./3. // 3.3333333333333331e-001
以下是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
结果在我尝试过的所有地方都是一样的——编译的 F# 3.1/.NET 4.0 应用程序,Visual Studio 2013 和 2015 中的 FSI,.NET Fiddle,@fsibot....
这肯定是某个地方的错误,不是吗?这是怎么回事?
这就是浮点数的工作原理。在输出中显示为 29 的数字实际上比 29 略小(因为浮点数不精确):
> (System.Math.Round(0.2916, 2) * 100.0) - 29.0;;
val it : float = -3.552713679e-15
float
是二进制浮点数据类型。并非所有十进制浮点值都可以精确表示为二进制浮点数。 FSI 显示为 29
实际上是 28.999999999999996
.
如果要存储精确的十进制浮点值,请使用 decimal
数据类型(使数字文字 decimal
而不是 float
添加 m
- 例如 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
您可以像 Matlab 一样更改 F# FSI Pretty Printer "format long"
fsi.AddPrinter( fun (x:float) -> sprintf "%26.16e" x);;
FSI输出
System.Math.Round( 0.2916, 2) // 2.8999999999999998e-001
1./3. // 3.3333333333333331e-001