小浮点值的Swift数学运算

时间:2015-03-13 02:12:28

标签: xcode swift floating-point-precision

我正在运行这样的for循环:

for var i: Float = 1.000; i > 0; i -= 0.005 {
    println(i)
}

我发现在i减少超过某个值而不是减少精确0.005后,它会比0.005略微减少,所以当它到达时在201迭代中,i不是0,而是无限小关闭0,因此for循环运行。输出如下:

1.0
0.995
0.99 
0.985
... 
0.48
0.475001
0.470001
...
0.0100008 // should be 0.01
0.00500081 // should 0.005
8.12113e-07 // should be 0

我的问题是,首先,为什么会发生这种情况,其次,我可以做些什么,i总是减少0.005,以便循环不会在201迭代上运行?

非常感谢,
bigelerow

1 个答案:

答案 0 :(得分:0)

Swift浮点数documentation表示:

  

请注意
  Double的精度至少为15位十进制数,而Float的精度可以小至6位十进制数。要使用的适当浮点类型取决于您在代码中使用的值的性质和范围。在任何一种类型都适合的情况下,首选Double。

在这种情况下,基于200次减法后剩余的数量,看起来每次减法中的误差大约为4.060564999999999e-09。实际上,将Float更改为Double会降低精度,使得循环运行到i = 0.00499999999999918时应该0.005

这一切都很好,但是我们仍然存在构造循环的问题,该循环将一直运行直到i变为零。如果你减少的i减去的量在整个循环中保持不变,那么只有一个不幸的解决方法是:

var x: Double = 1
let reduction = 0.005

for var i = Int(x/reduction); i >= 0; i -= 1, x = Double(i) * reduction {
    println(x)
}

在这种情况下,您的错误不会复合,因为我们使用整数来索引到达当前x所需的减少量,因此与循环的长度无关。