我想知道为什么在做加法运算时,Swift会弄乱浮点数的精度。
以下是从127.1
开始并向其添加0.1
的简单示例。
var value: Float = 127.1
for number in 0...5 {
print(value)
value += 0.1
}
这是我得到的结果..
127.1
127.2
127.299995
127.399994
127.49999
127.59999
..。我所期待的是这样的:
127.1
127.2
127.3
127.4
127.5
127.6
有人能解释一下为什么会发生这种情况吗?如果我能做些什么来保持我所需的一位小数精度呢?
**注意:**我知道我可以按照我需要的精度将其格式化为字符串,但当我需要执行数学运算并且不能依赖数字的精度时,这对我没有帮助。
**更新:**我确实找到了一本interesting article,它讲述了计算机如何处理浮点数学,在某种程度上回答了为什么会发生这种情况,但我很好奇其他人认为获得我需要的结果的最佳方法是什么。
**更新:**我找到的最好的解决方案是转换为整数来进行数学计算,然后再转换回浮点数...
var value: Float = 127.1
for number in 0...9 {
print(value)
var valueAsInt: Int = Int(value * 10)
valueAsInt += 1
value = Float(valueAsInt)/10
}
1条答案
按热度按时间f0ofjuux1#
这是由SWIFT的默认浮点数字格式造成的。
在每次迭代中计算的实际值为:
在第二个数字之后,由于累计舍入误差,这些值与最接近127.1、127.2、127.3、127.4、127.5和127.6的
Float
值不同。最接近这些数字的Float
类型的值为:正如您所看到的,其中127.1和127.2是相同的,SWIFT向您显示了“127.1”和“127.2”。对于其他情况,SWIFT会显示更多数字,从而将计算值与序列127.1、127.2、127.3、127.4、127.5和127.6中的相应值区分开来。
我怀疑SWIFT的默认格式生成的数字刚好足以唯一区分真实的
Float
值。换句话说,它显示了足够多的数字,将显示的数字转换回Float
将复制Float
值。对于第二个数字之后的情况,仅在小数点后生成一个数字不能实现这一点,因此SWIFT生成更多的数字。如果要使用最接近127.1、127.2、127.3、127.4、127.5和127.6的
Float
值执行循环,只需迭代一个从1271到1276的整数值(可以是Float
类型),并将value
设置为除以十。使用这种技术,在每次迭代中,value
将只受除法中的一个舍入误差的影响,因此它的Float
值将最接近所需的数字。在迭代过程中不会累积误差。