【发布时间】:2021-07-20 16:05:27
【问题描述】:
#include <stdio.h>
int main() {
printf("%.14f\n", 0.0001f * 10000000.0f); // 1
printf("%.14f\n", 0.001f * 1000000.0f); // 2
printf("%.14f\n", 0.01f * 100000.0f); // 3
return 0;
}
这段代码的输出是:
1000.00000000000000
1000.00006103515625
1000.00000000000000
我知道,小数不能用浮点数精确表示。但是为什么第 1 行和第 3 行的计算正确而第 2 行却没有?您对这里的详细情况有清楚的解释吗?
【问题讨论】:
-
埃里克很快就会给出一个更好的答案,所以我只想说:有时你会在一个地方四舍五入,在另一个地方四舍五入,然后他们取消了。此外,一般来说,您不一定会说第 1 行和第 3 行的计算正确,只是剩余的错误小于
%.14f会显示。 (但是,是的,对于传统的double,%.14f应该向您展示几乎所有内容。) -
扩展我的第一条评论,最接近 0.01 的浮点数是
0.0099999997,最接近 0.001 的浮点数是0.001000000047,最接近 0.0001 的浮点数是0.000099999997。所以有一点规律。 -
“即使是停止的时钟一天也能正确两次。” :-)
-
设计浮点算法的人花了很多时间试图满足这个要求,因为这并不总是那么容易。通常,您必须在内部使用更多(有时更多)位来保存中间结果,以便最终结果可以正确四舍五入。最终结果应该在半个“unit in the last place”以内。
-
例如,
hypot(x,y)被定义为只做sqrt(x*x + y*y),但在 glibc 中实现为更复杂的github.com/bminor/glibc/blob/master/sysdeps/ieee754/dbl-64/…,以免导致溢出并保持准确性
标签: c floating-point