我在 Windows 7 上使用 Code::Blocks 10.05。
我编译了下面的程序,
#include<stdio.h>
int main()
{
float f=1.5;
printf("%f\n",(f-1)*1/2);
return 0;
}
输出为 0.250000。 我的理解如下,
由于 f
是一个 float (f-1)
返回一个浮点值 0.500000 并且整个表达式升级为浮点运算因此 1/2 也被视为 float 以获得 0.500000 并因此得到结果。
还有如下声明,
float f=1.5;
printf("%f\n",1/2*(f-1));
给出了 0.000000 作为答案。
这里表达式 1/2
执行整数除法。在这里,我希望首先对 (f-1)
求值,然后将整个表达式升级为浮点运算。
这里我再次想到,因为波兰符号是,
* / 1 2 - f 1
除法是执行的第一个操作,因此是结果。 我对这个假设是否正确?
最后下面的语句违背了所有的逻辑,
float f=1.5;
printf("%f\n",(f-1)*(1/2));
输出为0.000000, 但这里的波兰符号是,
* - f 1 / 1 2
所以 (f-1)
应该首先被评估,因此整个表达式升级为 float
点运算,输出应为 0.250000。
我哪里错了? 这与运算符 * 的评估顺序有关吗? C 中的表达式是否有歧义?
最佳答案
Since f is a float (f-1) returns a float value of 0.500000 and the whole expression is upgraded to floating point arithmetic
不,你从哪里得到这些错误信息?提升为 float 仅适用于任一操作数为 float 的运算符。 1/2
不被视为浮点表达式——因此,它甚至没有被计算。由于乘法和除法具有相同的优先级并且是左结合的,
(f - 1) * 1 / 2
被评估为
((f - 1) * 1) / 2)
在那里,1
被提升为 float
(至少),然后因为 ((f - 1) * 1)
是 float ,然后除法的另一个操作数 2
也被提升为 float
(或更高精度的 FP 数,具体取决于编译器的要求)。
Here I expected (f-1) to be evaluated first and the whole expression to be upgraded to floating point arithmetic.
不,正如我刚才所解释的那样,这是一个不正确的期望。它不是要转换为 float 的完整表达式。它只是运算符的另一个直接操作数,其中一个操作数是float
。因此在表达式中:
(f - 1) * (1 / 2)
f - 1
是一个 float
。 1/2
是一个整数,它是零,然后整数零被提升为float
,因为*
的另一个操作数是一个 float
。而/
的操作数是整数,所以除法是根据整数运算规则计算的。
关于c - C 中的浮点计算顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25076245/