3

我试图将浮点数显示到小数点后一位。我得到了意想不到的结果,如下所示:

代码:

float a = 1.25;
float b = 1.35;

NSLog(@"1.25 -> %.1f\n1.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 -> %.30f\n1.35 -> %.30f",a,b);

1.25 -> 1.250000000000000000000000000000

1.35 -> 1.350000000000000088817841970013

很多很好的信息,但据我所知,没有人解决第二个问题:我如何获得预期的行为?

Objective-C 中的四舍五入是一个完全不同的问题。

4

2 回答 2

5

1.35 是 27/20,二进制是

1.01 0110 0110 0110 0110 0110 0110....

Afloat在大多数系统上都有一个 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使用“四舍五入”进行十进制输出!我在这个 ideone 链接检查了这个假设,确实 1.75 被四舍五入到 1.8。这对我来说是一个惊喜,但不是一个大惊喜。

于 2013-03-31T10:29:44.377 回答
2

那是因为浮点数不准确。%.1f打印四舍五入到小数点后一位的数字,但是,它似乎1.35不能精确地表示为 1.2500000,而是可以是一个稍小的数字。

在此处阅读有关此行为的信息:每位计算机科学家都应该了解浮点数

于 2013-03-31T10:00:57.433 回答