浮点数取整

4

您能解释一下这段代码吗:

  printf("Value1: %0.1f \n", (float)124/100); // = 1.2
  printf("Value1: %0.1f \n", (float)125/100); // = 1.2
  printf("Value1: %0.1f \n", (float)126/100); // = 1.3
  printf("\n");
  printf("Value2: %0.1f \n", (float)134/100); // = 1.3
  printf("Value2: %0.1f \n", (float)135/100); // = 1.4
  printf("Value2: %0.1f \n", (float)136/100); // = 1.4

为什么数字125舍入到1.2,而数字135舍入到1.4? 例如,这也会发生在数字105、115、125、155和165上。

2
它可能使用银行家舍入法。 - Szabolcs
3
你使用的是哪个平台/编译器?在MSVC中,第125行实际上显示为1.3(按照你的预期四舍五入)。 - wohlstad
4
1.35 四舍五入是因为 1.35 实际上是 1.35000002384185791015625。 - user3386109
2
你需要比较1.25和1.75来看真正的四舍五入,因为它们在二进制浮点数中可以精确表示,而1.35则不行。 - phuclv
2
我解释不清为什么在gcc / glibc x86 Linux上,if(fegetround()== FE_TONEAREST){printf(“Value1:%0.1f%。20f \ n”,(double)125/100,1.25); printf(”Value1:%0.1f%。20f \ n“,(double)175/ 100,1.75);} 会打印出Value1:1.2 1.25000000000000000000 Value1:1.8 1.75000000000000000000。我认为这与printf内部和7.21.6.1的语言法律有关:“表示浮点数的双精度参数以样式[−]ddd.ddd转换为十进制表示法,小数点字符后面的数字位数等于精度规范。” - Lundin
显示剩余11条评论
1个回答

4
C标准没有完全规定float格式或舍入方式。今天大多数C实现使用IEEE-754二进制32位格式表示float。在此格式中:
- 最接近1.24的可表示值是1.2400000095367431640625。 - 最接近1.25的可表示值是1.25。 - 最接近1.26的可表示值是1.2599999904632568359375。 - 最接近1.34的可表示值是1.34000003337860107421875。 - 最接近1.35的可表示值是1.35000002384185791015625。 - 最接近1.36的可表示值是1.36000001430511474609375。
如果你将printf调用中的%0.1f更改为%.99g,则你的C实现可能会显示这些值。
最常用的舍入规则是四舍五入到最接近的可表示值,如果有一种平局,则向带有偶数低位数字的平局值舍入。当执行算术运算(尤其是加减乘除)时,通常使用此规则。因此,在计算(float)124/100等式时,你的C实现可能会使用它。
在将数字从内部二进制float格式转换为字符字符串中的数字时,如printf,该规则也经常用于四舍五入。 (在这种情况下,该规则使用得较少,因为某些转换软件未编写使用必要的精度或计算以始终根据此规则产生正确的结果。)你观察到的输出与使用此规则一致:
- 将1.2400000095367431640625四舍五入到小数点后一位,产生“1.2”,因为它比1.3更接近1.2。 - 将1.25四舍五入到小数点后一位,产生“1.2”,因为1.2和1.3平局,并且1.2具有偶数低位数字。 - 将1.2599999904632568359375四舍五入到小数点后一位,产生“1.3”,因为它比1.2更接近1.3。 - 将1.34000003337860107421875四舍五入到小数点后一位,产生“1.3”,因为它比1.4更接近1.3。 - 将1.35000002384185791015625四舍五入到小数点后一位,产生“1.4”,因为它比1.3更接近1.4。 - 将1.36000001430511474609375四舍五入到小数点后一位,产生“1.4”,因为它比1.3更接近1.4。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接