我正在运行一个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
所需的缩减量,因此与循环的长度无关。