浮点数学精度,C ++与Fortran

时间:2020-02-25 21:37:09

标签: c++ fortran

我试图在C ++和Fortran中实现一个递归函数,该函数计算x处第n个Legendre多项式的值。在Fortran中,我有

************* Module code.cars                                                                                                
cars.py:3:0: C0304: Final newline missing (missing-final-newline)                                                             
cars.py:1:0: C0114: Missing module docstring (missing-module-docstring)                                                       
cars.py:1:0: C0103: Class name "cars" doesnt conform to PascalCase naming style (invalid-name)                               
cars.py:1:0: C0115: Missing class docstring (missing-class-docstring)                                                         
cars.py:1:0: R0903: Too few public methods (0/2) (too-few-public-methods)                                                                                                                                                                                   
------------------------------------                                                                                          
Your code has been rated at -6.67/10  

然后在C ++中我有

recursive function legendre(n, x) result(p)
  integer, intent(in) :: n
  real(8), intent(in) :: x
  real(8) :: p

  if(n == 0) then
    p = 1.0
  else if (n == 1) then
    p = x
  else
    p = (2.0*real(n,dp)-1.0)*x*legendre(n-1,x)-(real(n,dp)-1.0)*legendre(n-2,x)
    p = p / real(n,dp)
  end if 
end function legendre

这两个函数对我来说似乎完全相同,都使用双重精度,但是Fortran函数的结果与C ++的结果有很大不同。例如, 根据WolframAlpha,legendre(7,-0.2345)= 0.28876207107499049178814404296875上面的两个代码在没有优化的情况下编译时会产生

Fortran:0.28876206852410113

C ++:0.28876207107499052285

我知道由于浮点运算,答案应该不一样,但是对我来说,双精度的值差异似乎很大。 Fortran值与其他两个值相差太远的原因是什么?

2 个答案:

答案 0 :(得分:5)

尽管FORTRAN函数中的变量被定义为双精度(8字节),但是您指定的常量是默认值(单精度) ,4字节)的值。

根据this discussion,这意味着该算术以单精度精度执行:

即使定义了要将结果分配给的变量, 要成为DP,Fortran标准 要求 使用SP执行常量。那是因为您使用默认 实常数,因为您在处没有任何类型参数 常量的末尾。根据规则,默认实数为SP。

然后,在相同的讨论中进一步进行:

...从1991年6月发布的Fortran 90开始,这种做法 禁止将SP常量“提升”到DP。

因此,为了强制执行双精度数学运算,请将常量指定为DP:例如,1.0(而不是1.0D0)(对于其他常量,以此类推)代替。

答案 1 :(得分:4)

借助Adrian的回应,我得以解决此问题。 Fortran函数中的代码没什么错,问题是我传递给它的x的值。即使在主程序中,我将x定义为real(8),后者也通过简单的方式为它分配了值

x = -0.2345

我认为应该是双精度。实际上应该是

x = -0.2345_dp

这将导致两个函数具有相同的答案。我相信这可能是由于阿德里安指出的原因。

相关问题