Fortran sqrt的复数-1给出了不同的结果

ale*_*xis 5 fortran complex-numbers

这段代码

print *, sqrt(cmplx(-1))
print *, sqrt(cmplx(-1,0))
print *, sqrt((-1,0))
print *, sqrt(-(1,0))
Run Code Online (Sandbox Code Playgroud)

给了我这个输出

(0.00000000,1.00000000)
(0.00000000,1.00000000)
(0.00000000,1.00000000)
(0.00000000,-1.00000000)
Run Code Online (Sandbox Code Playgroud)

我相信正确的代数是sqrt(-1)=i.为什么最后一行的结果?

编译器版本是GCC 7.3.0,在Linux openSUSE 42.2(x86_64)上运行.

编辑

关注@francescalus回答我尝试过更多案例:

print *, sqrt((-1,-0))
print *, sqrt((-1,-0.))
print *, (-1,-0)
print *, (-1,-0.)
Run Code Online (Sandbox Code Playgroud)

我明白了

(0.00000000,1.00000000)
(0.00000000,-1.00000000)
(-1.00000000,0.00000000)
(-1.00000000,-0.00000000)
Run Code Online (Sandbox Code Playgroud)

所以,似乎我的编译器支持real数字的负零.所以,我想在使用这样的变量时要小心:

complex             :: asd 
asd=(1.,0.)
print *, sqrt(-asd)
Run Code Online (Sandbox Code Playgroud)

在这里,我再次得到错误的结果,但零负面的事情更难以预测.我有这么多问题!你知道其他一些可能导致错误的例子吗?你有建议避免这个错误吗?你现在有一些编译器标志来关闭GCC编译器的负面cero支持吗?

fra*_*lus 5

Fortran 2008 (13.7.159) 将sqrt函数的结果定义为参数X,为(我的重点):

结果的值等于 X 的平方根的依赖于处理器的近似值。 complex 类型的结果是实部大于或等于零的主值。当结果的实部为零时,虚部与 X 的虚部符号相同。

你的平方根确实有零实部,所以让我们看看你的论点虚部的符号。的虚部的符号是什么-(1,0)?如果您的处理器支持有符号零,那么它很可能是负数。在这种情况下,根据标准的要求,结果的虚部应为负数。

在所有其他情况下,没有理由期望参数的虚部为零,而不是正数。