使用%.1f时打印的意外值



我试图将浮点数显示为一个小数点。我得到了以下意想不到的结果:

代码:

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,相反,它是一个稍微小一点的数字。

关于浮点数,每个计算机科学家都应该知道的事情

最新更新