我遇到了在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
让我知道这个问题以及如何解决这个问题。
答案 0 :(得分:7)
问题是你还没有意识到浮点的一个固有问题:大多数数字都不能完全表示(a)。
这意味着4.845
实际上可能类似于4.8449999999999
,当你围绕它时,它会给你4.84
而不是你期望的4.85
484.5
}。
你最终得到的价值还取决于你如何计算它,这就是你得到不同结果的原因。
当然,如果没有权威的What Every Computer Scientist Should Know About Floating-Point Arithmetic,那么在SO上就不会有完整的“不准确”答案。
(a)在IEEE754中,只能在一定的相似范围内精确渲染两个精确幂的和。因此,例如,256 + 128 + 64 + 32 + 4 + 0.5
是
28 + 27 + 26 + 25 + 22 + 2-1
(double
)。
有关IEEE754格式的更详细信息,请参阅this answer。
至于解决它,你有几个选择。一种是使用float
而不是0.1
。这样可以提供更高的精度和更大的数字范围,但只能将问题进一步推移而不是真正解决问题。由于NSDecimalNumber
是IEEE754中的重复分数,因此 no 位数(无穷大)可以准确地代表它。
另一个选择是使用像大十进制类型的自定义库,它可以表示任意精度的小数(这是不无限精度,因为有些人不会建议,因为它受内存限制) 。这将减少二进制/十进制不匹配引起的错误。
您可能还想查看{{1}} - 这不会给您任意精度,但它确实提供了具有精确十进制表示的大范围。
仍然有一些你无法代表的数字,比如PI或2的平方根或任何其他无理数,但它应涵盖大多数情况。如果确实需要处理其他值,则需要切换到符号数字表示。
答案 1 :(得分:2)
与可以完全表示为float * 的484.5
不同,4.845
表示为4.8449998
(如果您愿意,请参阅this calculator尝试其他数字)。乘以100将数字保持在484.49998
,正确舍入到484
。
0.5
是2的幂(即2^-1
)。