我正在运行一个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次迭代中运行了?
谢谢,
大羚羊

最佳答案

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所需的缩减量,因此与循环的长度无关。

10-08 15:42