Mic*_*ero 13 c++ clang complex-numbers
当我使用g ++(4.8.1或4.9.0)或clang ++(3.4)编译以下代码时,我得到不同的输出.
#include <iostream>
#include <complex>
int main() {
std::complex<double> c = {1.e-162,0};
std::cout << 1.0/c << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
克++:
(1e+162,0)
Run Code Online (Sandbox Code Playgroud)
铛++:
(inf,-nan)
Run Code Online (Sandbox Code Playgroud)
这是clang中的错误吗?
更新:
谢谢您的回答!我报告了这个错误:http://llvm.org/bugs/show_bug.cgi?id = 19820
该标准在[complex.numbers](26.4/3)中说:
如果函数的结果未在数学上定义或未在其类型的可表示值范围内,则行为未定义.
关于如何对复数进行划分没有具体细节.只有[complex.member.ops]它说:
Run Code Online (Sandbox Code Playgroud)complex<T>& operator/=(const complex<T>& rhs);效果:将复数值除以
rhs复数值*this并存储商*this.返回:*this.
并在[complex.ops]:
Run Code Online (Sandbox Code Playgroud)template<class T> complex<T> operator/(const T& lhs, const complex<T>& rhs);返回:
complex<T>(lhs) /= rhs.
作为1.e-162is 的倒数,1.e+162并且该数字在a的可表示值的范围内double,行为被很好地定义.
因此gcc做对了,clang有一个bug.
更新:
\n\n引用自标准:
\n\n\n\n\n如果在计算表达式期间,结果不是\n 数学定义的或不在其类型的可表示值的范围内,则行为是未定义的\xef\xac\x81ned。[ 注意:大多数现有的 C++ 实现都会忽略 xef\xac\x82ows 上的整数。除以零的处理,使用零除数形成余数,并且所有 \xef\xac\x82oating\n 点异常因机器而异,通常可以通过库函数进行调整]。
\n
引用自 http://lists.freebsd.org/pipermail/freebsd-numerics/2014-March/000549.html:
\n\n\n\n\n看来 clang 开发人员选择了朴素的复杂除法算法。
\n\n...
\n\n我做了一些 grepping。除法算法是否包含在函数 ComplexExprEmitter::EmitBinDiv 内的文件 src/contrib/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp 中?
\n\n如果您查看代码,它肯定看起来正在生成代码来执行复杂的除法,并且看起来肯定使用的是朴素算法。
\n
假设 clang 确实使用朴素的复杂除法,则表达式1.0 / c根据复杂除法的朴素实现对以下表达式进行计算 \n
,

1.e-324超出双范围。这会导致根据标准出现未定义的行为。
\n\n另外在LLVM/Clang bug list中搜索了一下,似乎有不少关于复杂除法的问题。
\n\n因此,您的情况是一个错误,您应该报告它。
\n\n对于任何对如何实现稳健的复杂除法感兴趣的人,请看一下
\n\n\n| 归档时间: |
|
| 查看次数: |
930 次 |
| 最近记录: |