#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;
}
Godbolt https://godbolt.org/z/b1abenra3
这段代码的输出是:
1000.00000000000000
1000.00006103515625
1000.00000000000000
我知道,小数不能用浮点数精确表示。但为什么要计算第 1 行和第 3 行正确地2 不是吗?您对这里发生的事情的详细情况有清楚的解释吗?
有时,累积舍入(OP 样本中每个步骤 3 步)的结果与数学/小数结果相同,有时则不然。@史蒂夫峰会 https://stackoverflow.com/questions/68458045/explanation-for-floating-point-rounding-effect#comment120987379_68458045, @史蒂夫峰会 https://stackoverflow.com/questions/68458045/explanation-for-floating-point-rounding-effect#comment120987806_68458045
详细解释这里发生的事情?
每行代码有 3 个潜在舍入步骤:
-
Source code to float
. Recall common float https://en.wikipedia.org/wiki/Single-precision_floating-point_format are of the form: some_limited_integer * 2some_power.
-
float
带舍入的乘法
-
Printing of a float
rounded to 14 decimal places*1.
For printf("%.14f\n", 0.0001f * 10000000.0f); // 1
-
Code 0.0001f
to a float
值为 0.0000999999974737875163555145263671875
-
0.0000999999974737875163555145263671875 * 10000000.0 --> 999.999974737875163555145263671875 --> 四舍五入到最接近的值float
--> 1000.0
-
1000.0 -->"1000.00000000000000"
.
For printf("%.14f\n", 0.001f * 1000000.0f); // 2
-
Code 0.001f
to a float
值为 0.001000000047497451305389404296875
-
0.001000000047497451305389404296875 * 1000000.0 --> 1000.000047497451305389404296875 --> 四舍五入到最接近的float
--> 1000.00006103515625
-
1000.00006103515625 -->"1000.00006103515625"
.
在#1 中,四舍五入先向下,然后向上 - 倾向于取消。
在#2 中,舍入不断向上 - 导致显着的结果双舍入 https://en.wikipedia.org/wiki/Rounding#Double_rounding effect.
粗略地说,每个步骤最多可注入 1/2ULP https://en.wikipedia.org/wiki/Unit_in_the_last_place error.
其他考虑因素:1)替代舍入模式。上面使用四舍五入到最接近的值。 2) 库薄弱。以上假设质量printf()
.
*1 In OP's samples, there was no rounding error. In general, printing float
with "%f"
can round.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)