【发布时间】:2024-01-08 17:54:01
【问题描述】:
我有这个代码
#define Third (1.0/3.0)
#define ThirdFloat (1.0f/3.0f)
int main()
{
double a=1/3;
double b=1.0/3.0;
double c=1.0f/3.0f;
printf("a = %20.15lf, b = %20.15lf, c = %20.15lf\n", a,b,c);
float d=1/3;
float e=1.0/3.0;
float f=1.0f/3.0f;
printf("d = %20.15f, e = %20.15f, f = %20.15f\n", d,e,f);
double g=Third*3.0;
double h=ThirdFloat*3.0;
float i=ThirdFloat*3.0f;
printf("(1/3)*3: g = %20.15lf; h = %20.15lf, i = %20.15f\n", g, h, i);
}
哪个给出了输出
a = 0.000000000000000, b = 0.333333333333333, c = 0.333333343267441
d = 0.000000000000000, e = 0.333333343267441, f = 0.333333343267441
(1/3)*3: g = 1.000000000000000; h = 1.000000029802322, i = 1.000000000000000
我假设a 和d 的输出看起来像这样,因为编译器在除法后将整数值转换为浮点数。
b 看起来不错,e 是错误的,因为 float 精度低,如 c 和 f。
但我不知道为什么g 有正确的值(我认为1.0/3.0 = 1.0lf/3.0lf,但后来i 应该是错误的)以及为什么h 与i 不同。
【问题讨论】:
-
对于
g...你没有注意到它是我的三倍吗? -
所以基本上你在问为什么
(1.0 / 3.0) * 3.0是1?为什么(1.0f / 3.0f) * 3.0没有输出1? -
Re
h与i:因为3.0是双精度,3.0f是浮点数 -
编译器往往非常擅长称为constant folding 的东西,其中编译时常量表达式在编译时进行评估。此外,优秀的编译器也可以很好地检测
g、h和i所示的情况,其中除以 3.0 后乘以3.0相互抵消。 -
关于常量折叠和计算,即使没有启用优化,GCC 10.2 也会将您的所有计算转换为常量值,如程序集here 中所示(查看最后的常量)。跨度>