我试图将浮点数显示为一个小数点。我得到了以下意想不到的结果:
代码:float a = 1.25;
float b = 1.35;
NSLog(@"1.25 -> %.1fn1.35 -> %.1f",a,b);
输出:1.25 -> 1.2
1.35 -> 1.4
期望输出:
1.25 -> 1.3
1.35 -> 1.4
或:
1.25 -> 1.2
1.35 -> 1.3
这仅仅是由于二进制和十进制之间的内部转换吗?如果是,我如何得到预期的行为?
我使用Xcode 4.6。
编辑:好的,感谢TonyK和H2CO3,这是由于小数的二进制表示。
float a = 1.25;
float b = 1.35;
NSLog(@"1.25 -> %.30fn1.35 -> %.30f",a,b);
1.25 -> 1.25 00000000000000000000000000000000
1.35 -> 1.350000000000000088817841970013
有很多好的信息,但据我所见,没有人接近第二个问题:我如何获得预期的行为?
在Objective-C中四舍五入是一个完全不同的问题。
1.35 = 27/20,二进制为
1.01 0110 0110 0110 0110 0110 0110....
A float
在大多数系统上有一个23位尾数(不包括隐含的前导1),所以它被四舍五入到
1.01 0110 0110 0110 0110 0110 1
(因为0110明显大于1000的一半)。所以当printf
看到它时,它严格大于1.35。因此1.4。
对于1.25,这完全可以用二进制表示为
1.01
所以printf
看到了它的确切值。但它如何接近1.25呢?学校教我们把5四舍五入到10。但是大多数现代系统在硬件级别使用一种称为"四舍五入"的默认舍入模式,因为它减少了累积舍入误差的影响。这意味着当一个数字正好在两个最接近的候选者之间时,它被四舍五入到偶数候选者。
因此,print
似乎使用"四舍五入"为十进制输出!我在这个链接上检查了这个假设,实际上1.75被四舍五入到1.8。
这是因为浮点数不是精确的。%.1f
输出四舍五入到小数点后一位的数字,然而,1.35
似乎不能精确地表示为12500000,相反,它是一个稍微小一点的数字。