Fortran COMPLEX计算与C++不同

use*_*878 2 c++ matlab fortran numerical-computing

我已经完成了从Fortran到C++的端口,但发现了COMPLEX类型的一些差异.请考虑以下代码:

PROGRAM CMPLX
    COMPLEX*16 c
    REAL*8 a
    c = (1.23456789, 3.45678901)
    a = AIMAG(1.0 / c)
    WRITE (*, *) a
END
Run Code Online (Sandbox Code Playgroud)

而C++:

#include <complex>
#include <iostream>
#include <iomanip>

int main()
{
    std::complex<double> c(1.23456789, 3.45678901);
    double a = (1.0 / c).imag();

    std::cout << std::setprecision(15) << " " << a << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

使用clang ++或g ++编译C++版本,我得到输出:-0.256561150444368编译Fortran版本但是给了我:-0.25656115049876993

我的意思是,这两种语言都不符合IEEE 754吗?如果我在Octave(Matlab)中运行以下代码:

octave:1> c=1.23456789+ 3.45678901i
c =  1.2346 + 3.4568i
octave:2> c
c =  1.2346 + 3.4568i
octave:3> output_precision(15)
octave:4> c
c =  1.23456789000000e+00 + 3.45678901000000e+00i
octave:5> 1 / c
ans =  9.16290109820952e-02 - 2.56561150444368e-01i
Run Code Online (Sandbox Code Playgroud)

我和C++版本一样.Fortran COMPLEX类型有什么用?我错过了一些编译器标志吗?-ffast-math不会改变任何东西.我想在C++和Fortran中生成完全相同的15位小数,所以我更容易发现移植差异.

有任何Fortran大师吗?谢谢!

Hig*_*ark 5

在Fortran代码中替换

c = (1.23456789, 3.45678901)
Run Code Online (Sandbox Code Playgroud)

c = (1.23456789d0, 3.45678901d0)
Run Code Online (Sandbox Code Playgroud)

如果没有kind你在rhs上使用的真实文字,很可能是32位实数,你可能想要64位实数.后缀d0使编译器创建最接近您提供的值的64位实数.我已经掩盖了其中的一些细节,并且还有其他(可能更好)的方法来指定实数文字的类型,但是这种方法在任何当前的Fortran编译器上都可以正常工作.

我不太了解C++,我不确定C++代码是否有同样的问题.

如果我正确地读了你的问题,那么两个代码对8sf产生相同的答案,即单精度的极限.

至于IEEE-754合规性,据我所知,该标准并未涵盖复杂算术的问题.我希望在大多数情况下,幕后使用的fp算法会在预期的误差范围内产生复数的结果,但我不知道它们是保证的,因为fp算术的误差范围是.

  • 顺便说一句,在C++中,默认情况下所有浮点文字都是double.这才是我的原因. (3认同)