Fortran和C++计算的值之间的差异

plo*_*lok 6 c++ math fortran numeric

我敢说Fortran和C++计算的数值会更相似.然而,从我所经历的情况来看,事实证明,计算出的数字在十进制数字太少之后开始发散.在将一些遗留代码从前一种语言移植到后一种语言的过程中,我遇到了这个问题.最初的Fortran 77代码......

  INTEGER M, ROUND
  DOUBLE PRECISION NUMERATOR, DENOMINATOR

  M = 2
  ROUND = 1
  NUMERATOR=5./((M-1+(1.3**M))**1.8)
  DENOMINATOR = 0.7714+0.2286*(ROUND**3.82)
  WRITE (*, '(F20.15)') NUMERATOR/DENOMINATOR
  STOP
Run Code Online (Sandbox Code Playgroud)

...输出0.842201471328735,而它的C++等价...

int m = 2;
int round = 1;
long double numerator = 5.0 / pow((m-1)+pow(1.3, m), 1.8);
long double denominator = 0.7714 + 0.2286 * pow(round, 3.82);
std::cout << std::setiosflags(std::ios::fixed) << std::setprecision(15)
          << numerator/denominator << std::endl;
exit(1);
Run Code Online (Sandbox Code Playgroud)

...返回0.842201286195064.也就是说,计算值仅等于第六个小数.虽然不是特别是Fortran的倡导者,但我觉得它的结果是"正确的",因为它的数字cruncher的合法声誉.但是,我对计算值之间的这种差异的原因感到好奇.有谁知道造成这种差异的原因是什么?

jan*_*neb 11

在Fortran中,默认情况下,浮点文字是单精度,而在C/C++中它们是双精度.

因此,在您的Fortran代码中,计算NUMERATOR的表达式以单精度完成; 在将最终结果赋给NUMERATOR变量时,它仅转换为双精度.

对于计算分配给DENOMINATOR变量的值的表达式,也是如此.

  • 确切地。这是一个常见的错误——右侧的表达式不“知道”左侧的变量是双精度的。FORTRAN 77 指定浮点常量为双精度的方法是添加后缀“D0”——尝试将其添加到旧版 FORTRAN 代码中。 (2认同)