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

时间:2013-03-31 09:55:37

标签: objective-c c floating-point

我正在尝试将浮动显示为仅一个小数点。我得到了意想不到的结果如下:

代码:

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

很多好消息,但据我所知,没有人接近第二个问题:我如何得到预期的行为?

Rounding numbers in Objective-C是一个完全不同的问题。

2 个答案:

答案 0 :(得分:5)

1.35是27/20,二进制是

1.01 0110 0110 0110 0110 0110 0110....

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轮。但是大多数现代系统在硬件级别使用称为“round to even”的默认舍入模式,因为它减少了累积舍入误差的影响。这意味着当一个数字恰好位于两个最接近的舍入候选者之间时,它会四舍五入到偶数候选者。

所以似乎print正在使用“round to even”进行十进制输出!我在this ideone link检查了这个假设,确实1.75被四舍五入到1.8。这对我来说是一个惊喜,但不是一个巨大的。

答案 1 :(得分:2)

那是因为浮点数不准确。 %.1f将数字舍入打印到一个小数位,但似乎1.35无法准确表示为1.2500000,而是一个稍小的数字,可以是

在此处了解此行为:What every computer scientist should know about floating-point numbers