我在 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
让我知道这有什么问题以及如何解决这个问题。
我在 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
让我知道这有什么问题以及如何解决这个问题。
问题是您还没有意识到浮点的固有问题之一:大多数数字不能精确表示(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 的平方根或任何其他无理数,但它应该涵盖大多数情况。如果您确实需要处理这些其他值,则需要切换到符号数字表示。
与484.5
可以完全表示为 float *不同,4.845
它表示为4.8449998
(如果您想尝试其他数字,请参阅此计算器)。乘以 100 使数字保持在484.49998
,正确四舍五入为484
。
0.5
是 2 的幂(即2^-1
)。