c语言中浮点数四舍五入的逻辑是什么?
What logic works behind the rounding off of floating point number in c language?
我用c语言编写了一个程序来对浮点数进行四舍五入,但程序的输出不符合任何逻辑。
代码是-->
#include<stdio.h>
int main(){
float a=2.435000;
float b=2.535000;
float c=2.635000;
float d=2.735000;
float e=2.835000;
//Rounding off the floating point numbers to 2 decimal places
printf("%f %.2f\n",a,a);
printf("%f %.2f\n",b,b);
printf("%f %.2f\n",c,c);
printf("%f %.2f\n",d,d);
printf("%f %.2f\n",e,e);
return 0;
}
输出:
2.435000 2.43
2.535000 2.54
2.635000 2.63
2.735000 2.73
2.835000 2.84
所有的浮点数都具有相同的数字模式,即它们的形式为 2.x35000,其中 x 在不同的数字中是不同的。
我不明白为什么他们在四舍五入时表现出不同的行为,他们应该给出 2.x3 或 2.x4 但对于不同的 x 它给出不同的值。
这背后的逻辑是什么?
在你我看来 2.435 是一个很好的圆小数。
在你我看来,如果我们将它四舍五入到两个位置,我们会得到 2.44。
但是大多数计算机不会在内部使用小数,而你和我使用的肯定不会。他们使用 二进制 分数,二进制分数可能会令人惊讶。
在内部,事实证明数字 2.435 不能用二进制精确表示。作为 float
,它在内部表示为二进制分数,相当于 2.434999942779541015625。这非常接近 2.435,但您可以看到,如果将其四舍五入到两个位置,则会得到 2.43。
同样的论点可以解释你的其他结果。 2.635 实际上是 2.6349999904632568359375,因此四舍五入为 2.63。但是 2.535 是 2.5350000858306884765625,所以它四舍五入为 2.54,如您所料。
为什么我们不能接近 2.435?正如我所说,它在内部是一个二进制分数,相当于 2.434999942779541015625。实际的 IEEE-754 single-precision 表示是 0x401bd70a
,计算结果为 0x0.9bd70a × 2²
,或 0.60874998569488525390625 × 22。但是如果我们给它“加 1”,也就是说,如果我们让它尽可能大一点,下一个 float
值是 0x401bd70b
,即 0x0.9bd70b
或 0.608750045299530029296875 × 22,也就是2.4350001811981201171875,最终离2.435有点远。 (实际上是距离的三倍多。第一个数字相差 0.000000057;第二个相差 0.000000181。)
您可以在这些其他“规范的”SO 问题中阅读更多关于二进制浮点数有时令人惊讶的属性:
- Is floating point math broken?
- Why are floating point numbers inaccurate?
关于他们的另外两个有趣的问题——就在过去几天——是:
我用c语言编写了一个程序来对浮点数进行四舍五入,但程序的输出不符合任何逻辑。 代码是-->
#include<stdio.h>
int main(){
float a=2.435000;
float b=2.535000;
float c=2.635000;
float d=2.735000;
float e=2.835000;
//Rounding off the floating point numbers to 2 decimal places
printf("%f %.2f\n",a,a);
printf("%f %.2f\n",b,b);
printf("%f %.2f\n",c,c);
printf("%f %.2f\n",d,d);
printf("%f %.2f\n",e,e);
return 0;
}
输出:
2.435000 2.43
2.535000 2.54
2.635000 2.63
2.735000 2.73
2.835000 2.84
所有的浮点数都具有相同的数字模式,即它们的形式为 2.x35000,其中 x 在不同的数字中是不同的。 我不明白为什么他们在四舍五入时表现出不同的行为,他们应该给出 2.x3 或 2.x4 但对于不同的 x 它给出不同的值。
这背后的逻辑是什么?
在你我看来 2.435 是一个很好的圆小数。
在你我看来,如果我们将它四舍五入到两个位置,我们会得到 2.44。
但是大多数计算机不会在内部使用小数,而你和我使用的肯定不会。他们使用 二进制 分数,二进制分数可能会令人惊讶。
在内部,事实证明数字 2.435 不能用二进制精确表示。作为 float
,它在内部表示为二进制分数,相当于 2.434999942779541015625。这非常接近 2.435,但您可以看到,如果将其四舍五入到两个位置,则会得到 2.43。
同样的论点可以解释你的其他结果。 2.635 实际上是 2.6349999904632568359375,因此四舍五入为 2.63。但是 2.535 是 2.5350000858306884765625,所以它四舍五入为 2.54,如您所料。
为什么我们不能接近 2.435?正如我所说,它在内部是一个二进制分数,相当于 2.434999942779541015625。实际的 IEEE-754 single-precision 表示是 0x401bd70a
,计算结果为 0x0.9bd70a × 2²
,或 0.60874998569488525390625 × 22。但是如果我们给它“加 1”,也就是说,如果我们让它尽可能大一点,下一个 float
值是 0x401bd70b
,即 0x0.9bd70b
或 0.608750045299530029296875 × 22,也就是2.4350001811981201171875,最终离2.435有点远。 (实际上是距离的三倍多。第一个数字相差 0.000000057;第二个相差 0.000000181。)
您可以在这些其他“规范的”SO 问题中阅读更多关于二进制浮点数有时令人惊讶的属性:
- Is floating point math broken?
- Why are floating point numbers inaccurate?
关于他们的另外两个有趣的问题——就在过去几天——是: