我将在这里和下面的上下文中给出一个快速说明。我正在Python和Fortran中评估双变量多项式(2个变量的多项式)并得到不同的结果。我的测试用例 - 4.23e-3的相对误差足够大,不会因为精度差异而显着。下面的代码片段使用相当原始的类型和相同的算法来尝试尽可能地比较。任何关于差异的线索?我尝试了各种精度(包括Fortran中的selected_real_kind
和Python中的numpy.float128
),Fortran编译(特别是优化级别)和算法(Horner的方法,numpy
评估)。任何关于差异的线索?代码版本中的错误?我见过Precision discrepancy between Fortran and Python (sin function),但没有机会完全使用不同的编译器进行测试。Fortran和Python中的精度和多项式评估
的Python:
#!/usr/bin/env python
""" polytest.py
Test calculation of a bivariate polynomial.
"""
# Define polynomial coefficients
coeffs = (
(101.34274313967416, 100015.695367145, -2544.5765420363),
(5.9057834791235253,-270.983805184062,1455.0364540468),
(-12357.785933039,1455.0364540468,-756.558385769359),
(736.741204151612,-672.50778314507,499.360390819152)
)
nx = len(coeffs)
ny = len(coeffs[0])
# Values of variables
x0 = 0.0002500000000011937
y0 = -0.0010071334522899211
# Calculate polynomial by looping over powers of x, y
z = 0.
xj = 1.
for j in range(nx):
yk = 1.
for k in range(ny):
curr = coeffs[j][k] * xj * yk
z += curr
yk *= y0
xj *= x0
print(z) # 0.611782174444
的Fortran:
! polytest.F90
! Test calculation of a bivariate polynomial.
program main
implicit none
integer, parameter :: dbl = kind(1.d0)
integer, parameter :: nx = 3, ny = 2
real(dbl), parameter :: x0 = 0.0002500000000011937, &
y0 = -0.0010071334522899211
real(dbl), dimension(0:nx,0:ny) :: coeffs
real(dbl) :: z, xj, yk, curr
integer :: j, k
! Define polynomial coefficients
coeffs(0,0) = 101.34274313967416d0
coeffs(0,1) = 100015.695367145d0
coeffs(0,2) = -2544.5765420363d0
coeffs(1,0) = 5.9057834791235253d0
coeffs(1,1) = -270.983805184062d0
coeffs(1,2) = 1455.0364540468d0
coeffs(2,0) = -12357.785933039d0
coeffs(2,1) = 1455.0364540468d0
coeffs(2,2) = -756.558385769359d0
coeffs(3,0) = 736.741204151612d0
coeffs(3,1) = -672.50778314507d0
coeffs(3,2) = 499.360390819152d0
! Calculate polynomial by looping over powers of x, y
z = 0d0
xj = 1d0
do j = 0, nx-1
yk = 1d0
do k = 0, ny-1
curr = coeffs(j,k) * xj * yk
z = z + curr
yk = yk * y0
enddo
xj = xj * x0
enddo
! Print result
WRITE(*,*) z ! 0.61436839888538231
end program
编译时:gfortran -O0 -o polytest.o polytest.F90
上下文:我正在编写一个现有Fortran库的纯Python实现,主要是作为练习,但也增加了一些灵活性。我将我的结果与Fortran进行了比较,并且能够在大约1e-10的范围内获得几乎所有的结果,但是这一点在我的掌握之外。其他函数也更加复杂,使得简单多项式的分歧令人困惑。
特定的系数和测试变量来自这个库。实际的多项式实际上在(x,y)中有度(7,6),因此这里没有包含更多的系数。该算法直接来自Fortran,所以如果它是错误的,我应该联系原始开发人员。一般函数也可以计算衍生物,这是这种实现可能不是最优的原因之一 - 我知道我应该只写Horner的方法版本,但这并没有改变这种差异。在计算y的大数值时,我只注意到这些错误,但错误仍然存在于这个更简单的设置中。
如果他们都是相同的算法,你应该能够在两种实现之间的中间值进行比较,看看差异是如何进展的,如果有一个“罪魁祸首”,识别它。 –
我看了Fortran代码已经很长时间了,但看起来你的循环边界是不同的。例如,在Fortran代码中,'j'将从'0 - > 2(nx - 1)'去。在python代码中,'j'从'0 - > 3(len(coeffs) - 1)' – mgilson
也在Fortran中,您只将参数x0和y0设置为单精度。进一步,常量的规格是非常老式(f77)风格的怪异组合,以及更现代的使用类型值。 –