为什么斯威夫特会精准地做一些不可靠的事情?

lndjwyie  于 2022-10-04  发布在  Swift
关注(0)|答案(1)|浏览(175)

我想知道为什么在做加法运算时,Swift会弄乱浮点数的精度。

以下是从127.1开始并向其添加0.1的简单示例。

  1. var value: Float = 127.1
  2. for number in 0...5 {
  3. print(value)
  4. value += 0.1
  5. }

这是我得到的结果..

  1. 127.1
  2. 127.2
  3. 127.299995
  4. 127.399994
  5. 127.49999
  6. 127.59999

..。我所期待的是这样的:

  1. 127.1
  2. 127.2
  3. 127.3
  4. 127.4
  5. 127.5
  6. 127.6

有人能解释一下为什么会发生这种情况吗?如果我能做些什么来保持我所需的一位小数精度呢?

**注意:**我知道我可以按照我需要的精度将其格式化为字符串,但当我需要执行数学运算并且不能依赖数字的精度时,这对我没有帮助。

**更新:**我确实找到了一本interesting article,它讲述了计算机如何处理浮点数学,在某种程度上回答了为什么会发生这种情况,但我很好奇其他人认为获得我需要的结果的最佳方法是什么。

**更新:**我找到的最好的解决方案是转换为整数来进行数学计算,然后再转换回浮点数...

  1. var value: Float = 127.1
  2. for number in 0...9 {
  3. print(value)
  4. var valueAsInt: Int = Int(value * 10)
  5. valueAsInt += 1
  6. value = Float(valueAsInt)/10
  7. }
f0ofjuux

f0ofjuux1#

这是由SWIFT的默认浮点数字格式造成的。

在每次迭代中计算的实际值为:

  1. 127.09999847412109375
  2. 127.1999969482421875
  3. 127.29999542236328125
  4. 127.399993896484375
  5. 127.49999237060546875
  6. 127.5999908447265625

在第二个数字之后,由于累计舍入误差,这些值与最接近127.1、127.2、127.3、127.4、127.5和127.6的Float值不同。最接近这些数字的Float类型的值为:

  1. 127.09999847412109375
  2. 127.1999969482421875
  3. 127.3000030517578125
  4. 127.40000152587890625
  5. 127.5
  6. 127.59999847412109375

正如您所看到的,其中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值将最接近所需的数字。在迭代过程中不会累积误差。

展开查看全部

相关问题