iOS - 使用roundf()舍入浮点数不正常

时间:2013-03-16 07:48:12

标签: iphone objective-c math calc

我遇到了在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

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

2 个答案:

答案 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-1double)。

有关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)。