四舍五入甚至没有始终如一地应用?
round to even not consistently applied?
(上下文:我正在为嵌入式应用程序编写一个轻量级的 printf(),我希望它在实用时表现得像真正的 printf()。)
我知道 gcc 和其他行为良好的库使用 "round half to even"(又名 "Banker's rounding")来防止以下情况下的统计偏差:
printf("%0.0f %0.0f %0.0f %0.0f\n", 0.5, 1.5, 2.5, 3.5);
=> 0 2 2 4
令我惊讶的是,相同的舍入规则并未应用于其他精度:
printf("%0.1f %0.1f %0.1f %0.1f\n", 0.05, 0.15, 0.25, 0.35);
=> 0.1 0.1 0.2 0.3
这是预期的行为吗?我本以为:
=> 0.0 0.2 0.2 0.4
精通数值计算的人能解释一下哪种行为是理想的行为吗?为什么?
(注意:请参阅 http://rextester.com/IUXDW9788 了解实际示例。)
区别在于输入的数字,而不是格式。
0.5、1.5、2.5、3.5 和 0.25 都可以在 IEEE 754 64 位二进制中完全表示,这是 C double 的最可能实现,因此四舍五入规则适用。
最接近 0.05 的可表示值是 0.05000000000000000277555756156289135105907917022705078125,比 0.0 更接近 0.1
最接近 0.15 的可表示值是 0.1499999999999999944488848768742172978818416595458984375,比 0.2 更接近 0.1。
最接近 0.35 的可表示值是 0.34999999999999997779553950749686919152736663818359375,比 0.4 更接近 0.3。
四舍五入规则仅适用于恰好两个可能结果中间的数字,不适用于稍微接近其中一个可能结果的数字比另一个。
(上下文:我正在为嵌入式应用程序编写一个轻量级的 printf(),我希望它在实用时表现得像真正的 printf()。)
我知道 gcc 和其他行为良好的库使用 "round half to even"(又名 "Banker's rounding")来防止以下情况下的统计偏差:
printf("%0.0f %0.0f %0.0f %0.0f\n", 0.5, 1.5, 2.5, 3.5);
=> 0 2 2 4
令我惊讶的是,相同的舍入规则并未应用于其他精度:
printf("%0.1f %0.1f %0.1f %0.1f\n", 0.05, 0.15, 0.25, 0.35);
=> 0.1 0.1 0.2 0.3
这是预期的行为吗?我本以为:
=> 0.0 0.2 0.2 0.4
精通数值计算的人能解释一下哪种行为是理想的行为吗?为什么?
(注意:请参阅 http://rextester.com/IUXDW9788 了解实际示例。)
区别在于输入的数字,而不是格式。
0.5、1.5、2.5、3.5 和 0.25 都可以在 IEEE 754 64 位二进制中完全表示,这是 C double 的最可能实现,因此四舍五入规则适用。
最接近 0.05 的可表示值是 0.05000000000000000277555756156289135105907917022705078125,比 0.0 更接近 0.1
最接近 0.15 的可表示值是 0.1499999999999999944488848768742172978818416595458984375,比 0.2 更接近 0.1。
最接近 0.35 的可表示值是 0.34999999999999997779553950749686919152736663818359375,比 0.4 更接近 0.3。
四舍五入规则仅适用于恰好两个可能结果中间的数字,不适用于稍微接近其中一个可能结果的数字比另一个。