F#(和.NET)中的浮点精度

时间:2009-04-03 10:45:24

标签: f# floating-point

  1. 在“F# for Scientists”Jon Harrop说:

      

    粗略地说,int类型的值接近真实   min-int和max-int之间的数字,绝对误差为+ - 1/2   而float类型的值具有近似恒定的相对误差   只占百分之几。

    现在,这是什么意思? Int类型不准确?

  2. 为什么C#为(1 - 0.9)返回0.1但F#返回0.099999999999978? C#更准确,更适合科学计算吗?

  3. 我们应该使用十进制值而不是double / float来进行科学计算吗?

4 个答案:

答案 0 :(得分:6)

  1. 对于任意实数,整数类型或浮点类型仅提供近似值。积分近似在一个方向或另一个方向上永远不会超过0.5(假设实数适合该整数类型的范围)。浮点近似永远不会超过一小部分(同样,假设实数在该浮点类型支持的值范围内)。这意味着对于较小的值,浮点类型将提供更接近的近似值(例如,在浮点数中存储PI的近似值将比int近似值3更精确)。但是,对于非常大的值,积分类型的近似实际上将优于浮点类型(例如,考虑值9223372036854775806.7,当表示为9223372036854775807为长时,仅关闭0.3,但当存储为9223372036854780000.000000时由9223372036854780000.000000表示一个浮动)。

  2. 这只是一个关于如何打印值的工件。 9/10和1/10不能完全表示为浮点值(因为分母不是2的幂),就像1/3不能精确写成小数(你得到0.333 ...其中3的重复永远)。无论您使用何种.NET语言,此值的内部表示形式都是相同的,但打印值的不同方式可能会以不同方式显示。请注意,如果在FSI中评估1.0 - 0.9,结果将显示为0.1(至少在我的计算机上)。

  3. 您在科学计算中使用的类型将取决于您要实现的目标。您的答案通常只是近似准确。你需要多准确?您的性能要求是什么?我认为十进制类型实际上是一个固定点数,这可能使它不适合涉及非常小或非常大的值的计算。另请注意,F#包含任意精确有理数(使用BigNum类型),根据您的输入,这也可能是合适的。

答案 1 :(得分:2)

不,F#和C#使用相同的double类型。浮点几乎总是不准确。但整数是准确的。

更新:

您看到差异的原因是打印数字,而不是实际的表示。

答案 2 :(得分:2)

对于第一点,我会说int可以用来表示整数范围内的任何实数,在[-0,5,0.5]中有一个恒定的最大误差。这是有道理的。例如,pi可以用整数值3表示,误差小于0.15。

浮点数不共享此属性;它们的最大绝对误差与您尝试表示的值无关。

答案 3 :(得分:0)

3 - 这取决于计算:有时浮动是一个不错的选择,有时你可以使用int。但是当你缺少任何浮点数和小数的精度时,就会有任务。

反对使用 int 的原因:

> 1/2;; 
val it : int = 0

反对使用 float (在C#中也称为double)的原因:

> (1E-10 + 1E+10) - 1E+10;;
val it : float = 0.0

反对BCL的原因十进制

> decimal 1E-100;;
val it : decimal = 0M

每种列出的类型都有它自己的缺点。