Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/362.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
gcc编译器是否尊重我在代码中编写的表达式形式?_C_Gcc_Compiler Optimization_Numerical Stability - Fatal编程技术网

gcc编译器是否尊重我在代码中编写的表达式形式?

gcc编译器是否尊重我在代码中编写的表达式形式?,c,gcc,compiler-optimization,numerical-stability,C,Gcc,Compiler Optimization,Numerical Stability,比如说,我用c写了一个表达式 a = (((b+c) / d) / f) + ((3.14 * e) ) / f) ; 这里a、b、c、d、e、f都是双精度变量。例如,当我使用带有某些优化设置的gcc编译器编译代码时,编译器是否在编写时尊重表达式的特定形式,还是修改表达式以使代码运行更快?例如,gcc是否可以使用-O2优化设置将上述表达式编译为 a = ((b+c + 3.14* d * e) / (d*f)) 或者它会保持表达的原样?我担心编译器会更改方程式的形式,这可能会影响表达式的数值

比如说,我用c写了一个表达式

a = (((b+c) / d) / f) + ((3.14 * e) ) / f) ;
这里a、b、c、d、e、f都是双精度变量。例如,当我使用带有某些优化设置的gcc编译器编译代码时,编译器是否在编写时尊重表达式的特定形式,还是修改表达式以使代码运行更快?例如,gcc是否可以使用-O2优化设置将上述表达式编译为

a = ((b+c + 3.14* d * e) / (d*f))

或者它会保持表达的原样?我担心编译器会更改方程式的形式,这可能会影响表达式的数值稳定性。

编译器保证生成的表达式与编写公式时计算公式的结果相同。这包括表达式可能产生的所有类型转换、副作用和异常


特别是,优化表达式的方法不会通过等价性测试,因为原始表达式中的
((b+c)/d)
将根据
b
c
d
的类型进行评估,这些类型可以是
int
float
;另一方面,由于添加了
3.14
,您的第二个(优化)公式强制整个表达式上的
double
类型。它还将分子中的
e
乘以
d
,以补偿分母中的
d*f
,这可能会产生原始公式中不存在的溢出。

什么?它确实尊重您的程序的语义,并且只要您没有违反C标准中定义的任何规则,就可以保证生成与这些语义完全相同的结果。但是它是如何做到的——这主要取决于编译器。如果你想要的话,可能只是不添加-Ofast-funsafe数学优化或-ffast数学。像-O1、-Os、-O2或-O3这样的正常优化不应该出现。@technosaurus很有可能优化级别会改变评估的顺序,结果可能会有所不同。@PeterJ_01那么您的编译器不符合标准,或者您启用了未意识到的“不安全”优化。较旧的编译器在很久以前(大约20年前)就已经这样做了。。。因此,除非你的编译器真的很旧,或者你允许一个坏的构建系统来指定你的优化选项——这是不可能的。这不是100%的事实。对于运算符优先级和括号,表达式求值并没有特定的顺序。浮动操作的结果可能不同,因为如果计算顺序改变,浮动操作的结果可能不同。要避免此类问题,请使用parentheses@PeterJ_01我不是在谈论评估的顺序,它是实现定义的。的确,选择特定的求值顺序可能会影响表达式的值。但是,如果原始表达式应该计算产生异常的内容,调用带有副作用的函数两次,等等,那么编译器不能重写表达式以仅产生一次副作用,或者避免异常。例如,编译器不能重写
float x=…,a=1,b=a/x*x
b=a
,因为这将消除可能被零除的情况。是的,但IMO的问题是关于其他方面的。他问他是否可以100%肯定在不同的编译环境中他会得到相同的结果。但是没有这样的保证,结果可能会有所不同,@PeterJ_01 no.参考-产生的输出必须与抽象机器输出相同。因此,如果重新排列操作将导致不同的输出,则不应出现这种情况。根据我的经验,编译器会重新排列。如果计算顺序至关重要,100%确定使用比必要更多的括号更安全。