-1

我在 iPhone 应用程序中舍入浮点数时遇到问题。

float f=4.845;
float s= roundf(f * 100.0)/100;
    NSLog(@"Output-1: %.2f",s);
      s= roundf(484.5)/100;
    NSLog(@"Output-2: %.2f",s);

Output-1: 4.84
Output-2: 4.85

让我知道这有什么问题以及如何解决这个问题。

4

2 回答 2

7

问题是您还没有意识到浮点的固有问题之一:大多数数字不能精确表示(a)的事实。

这意味着4.845,在现实中,这很可能是类似的东西4.8449999999999,当你把它弄圆时,给你4.84而不是你所期望的,4.85

你最终得到的值也取决于你如何计算它,这就是你得到不同结果的原因。

当然,如果没有权威的What Every Computer Scientist Should Know About Floating-Point Arithmetic ,那么 SO 上的浮点“不准确”答案将是不完整的。


(a)在 IEEE754 中,只有在某个相似范围内的 2 的精确幂之和才能精确呈现。所以,例如,484.5

256 + 128 + 64 + 32 + 4 + 0.5( )。28 + 27 + 26 + 25 + 22 + 2-1

有关IEEE754 格式的更详细信息,请参阅此答案。


至于解决它,你有几个选择。一种是使用double而不是float. 这为您提供了更高的精度和更大的数字范围,但只会将问题移得更远,而不是真正解决它。由于0.1是 IEEE754 中的重复分数,因此没有多少位(小于无穷大)可以准确地表示它。

另一种选择是使用像大十进制类型这样的自定义库,它可以表示任意精度的小数(这不是一些人不会建议的无限精度,因为它受内存限制)。这将减少由二进制/十进制不匹配引起的错误。

您可能还想查看NSDecimalNumber- 这不会给您任意精度,但它确实提供了具有精确十进制表示的大范围。

仍然会有您无法表示的数字,例如 PI 或 2 的平方根或任何其他无理数,但它应该涵盖大多数情况。如果您确实需要处理这些其他值,则需要切换到符号数字表示。

于 2013-03-16T07:51:08.593 回答
2

484.5可以完全表示为 float *不同,4.845它表示为4.8449998(如果您想尝试其他数字,请参阅此计算器)。乘以 100 使数字保持在484.49998,正确四舍五入为484


*精确表示是可能的,因为它的小数部分0.5是 2 的幂(即2^-1)。

于 2013-03-16T07:55:04.470 回答