我试图在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值与其他两个值相差太远的原因是什么?
答案 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
这将导致两个函数具有相同的答案。我相信这可能是由于阿德里安指出的原因。