我正在运行这样的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
答案 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
所需的减少量,因此与循环的长度无关。