如何在MatLAB中获得Fortran精度

如何在MatLAB中获得Fortran精度,matlab,fortran,double-precision,Matlab,Fortran,Double Precision,我有一段用Fortran和Matlab编写的代码。他们做了完全相同的计算,即 构造一个tanh-字段并找到它的拉普拉斯算子 将一些项相乘 此乘法的结果产生一个矩阵,其(4,4)次和(6,6)次I相减 在Fortran语言中,它们的差别是~1e-20 在Matlab中,它们的差值相同为零 这个问题非常关键,因为我测试这个数字是否小于零。 问题:是否有一种方法可以执行计算,使我在Matlab中获得与Fortran相同的精度 我列出以下代码: MatLAB clear all weights

我有一段用Fortran和Matlab编写的代码。他们做了完全相同的计算,即

  • 构造一个
    tanh
    -字段并找到它的拉普拉斯算子
  • 将一些项相乘
  • 此乘法的结果产生一个矩阵,其(4,4)次和(6,6)次I相减

    • 在Fortran语言中,它们的差别是~1e-20
    • 在Matlab中,它们的差值相同为零
    这个问题非常关键,因为我测试这个数字是否小于零。 问题:是否有一种方法可以执行计算,使我在Matlab中获得与Fortran相同的精度

    我列出以下代码:


    MatLAB

    clear all
    
    weights = [4./9, 1./9,1./9,1./9,1./9, 1./36,1./36,1./36,1./36];
    dir_x   = [  0,   1,  0, -1,  0,    1,  -1,  -1,   1];
    dir_y   = [  0,   0,  1,  0, -1,    1,   1,  -1,  -1];
    
    
    
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CONSTANTS
    length_y = 11; length_x = length_y;
    y_center = 5; x_center  = y_center;
    
    
    densityHigh = 1.0;
    densityLow  = 0.1;
    radius  = 3.0;
    c_width = 1.0;
    
    average_density = 0.5*(densityHigh+densityLow);
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    
    
    
    
    
    for x=1:length_x
        for y=1:length_y
            for i=1:9
                fIn(i, x, y) = weights(i)*densityHigh;
                test_radius = sqrt((x-x_center)*(x-x_center) + (y-y_center)*(y-y_center));
                if(test_radius <= (radius+c_width))
                    fIn(i, x, y) = weights(i)*( average_density - 0.5*(densityHigh-densityLow)*tanh(2.0*(radius-sqrt((x-x_center)*(x-x_center) + (y-y_center)*(y-y_center))/c_width)) );
                end
            end
        end
    end 
    
    ref_density_2d = ones(length_x)*average_density;
    for i=1:length_x
        ref_density(:,:,i) = abs(ref_density_2d(:, i)');
    end
    
    
              rho = sum(fIn);
    laplacian_rho = (+1.0*(circshift(rho(1,:,:), [0, -1, -1]) + circshift(rho(1,:,:), [0, +1, -1]) + circshift(rho(1,:,:), [0, -1, +1]) + circshift(rho(1,:,:), [0, +1, +1])) + ...
                     +4.0*(circshift(rho(1,:,:), [0, -1, +0]) + circshift(rho(1,:,:), [0, +1, +0]) + circshift(rho(1,:,:), [0, +0, -1]) + circshift(rho(1,:,:), [0, +0, +1])) + ...
                    -20.0*rho(1,:,:));
    
    psi   = 4.0*0.001828989483310*(rho-densityLow).*(rho-densityHigh).*(rho-ref_density) - laplacian_rho*(1.851851851851852e-04)/6.0;
    
    psi(1,4,4)-psi(1,6,6) 
    
    全部清除
    权重=[4./9,1./9,1./9,1./9,1./9,1./9,1./36,1./36,1./36,1./36];
    dir_x=[0,1,0,-1,0,1,-1,1];
    dir_y=[0,0,1,0,-1,1,1,-1,-1];
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%常数
    长度y=11;长度x=长度y;
    y_中心=5;x_中心=y_中心;
    密度高=1.0;
    密度低=0.1;
    半径=3.0;
    c_宽度=1.0;
    平均密度=0.5*(密度高+密度低);
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    对于x=1:长度x
    对于y=1:长度
    对于i=1:9
    翅片(i,x,y)=重量(i)*密度高;
    测试半径=sqrt((x-x_中心)*(x-x_中心)+(y-y_中心)*(y-y_中心));
    
    如果(test_radius您仍然没有因此在代码中使用双精度,例如:

    beta     = 12.D0*0.0001/(1.D0*( (1.0 - 0.1)**4 ))
    
    还有更多。如果我强制编译器使用双精度作为浮点的默认值(对于
    gfortran
    ,编译选项是
    -fdefault-real-8
    ),那么代码的结果是:

    0.000000000000000000000000000000000000

    因此,您需要修复代码。例如,引用的行应为:

    beta     = 12.D0*0.0001D0/(1.D0*( (1.0D0 - 0.1D0)**4 ))
    

    [虽然我鄙视符号
    D0
    ,但这是另一回事]

    因此,您在代码中仍然没有使用双精度,例如:

    beta     = 12.D0*0.0001/(1.D0*( (1.0 - 0.1)**4 ))
    
    还有更多。如果我强制编译器使用双精度作为浮点的默认值(对于
    gfortran
    ,编译选项是
    -fdefault-real-8
    ),那么代码的结果是:

    0.000000000000000000000000000000000000

    因此,您需要修复代码。例如,引用的行应为:

    beta     = 12.D0*0.0001D0/(1.D0*( (1.0D0 - 0.1D0)**4 ))
    

    [虽然我鄙视符号
    D0
    ,但那是另一回事]

    尽管在回答这个问题的另一个版本()时有人建议你不要这样做,但你仍然在Fortran代码中使用单精度数字。默认情况下,
    0.1
    是Fortran中的单精度实数(除非你使用了编译器选项来调整通常的行为,我打赌你没有,你是不是这个小流氓?).这也许可以解释你观察到的差异。在你探索的这个阶段,你至少应该已经研究过这种可能性。我改变了它,使它使用双精度,但结论是一样的——结果仍然不同。我花了很长时间研究,相信我……对不起,但没有人可能会经历那么多代码(使用两种语言),运行并调试它。缩小问题范围。找出结果分歧的第一个地方。除了上面@HighPerformanceMark所说的之外,还请参阅我对上一个问题的评论–您需要检查像
    abs
    sqrt
    tanh
    等函数(甚至除法)在所有情况下返回相同的结果。并通过“检查”我的意思不是简单地打印到小数点后几位。@horchler我知道,我不能期望任何人这样做……但说真的,这太令人沮丧了,我无法让它工作。我还试着跟进
    tanh
    -的事情,他们在小数点后19位左右有所不同。但我没有办法补救这一点……我收回了我对是一个问题,并投票决定关闭另一个问题。@AlexanderVogt的回答是正确的,下面的答案是正确的,但属于这个问题,而不是另一个缺少Fortran代码的问题。尽管在对这个问题的另一个版本的回答中有其他建议()您仍然在Fortran代码中使用单精度数字。默认情况下,
    0.1
    是Fortran中的单精度实数(除非您使用了编译器选项来调整通常的行为,我打赌您没有,您是不是小流氓?).这也许可以解释你观察到的差异。在你探索的这个阶段,你至少应该已经研究过这种可能性。我改变了它,使它使用双精度,但结论是一样的——结果仍然不同。我花了很长时间研究,相信我……对不起,但没有人可能会经历那么多代码(使用两种语言),运行并调试它。缩小问题范围。找出结果分歧的第一个地方。除了上面@HighPerformanceMark所说的之外,还请参阅我对上一个问题的评论–您需要检查像
    abs
    sqrt
    tanh
    等函数(甚至除法)在所有情况下返回相同的结果。并通过“检查”我的意思不是简单地打印到小数点后几位。@horchler我知道,我不能期望任何人这样做……但说真的,这太令人沮丧了,我无法让它工作。我还试着跟进
    tanh
    -的事情,他们在小数点后19位左右有所不同。但我没有办法补救这一点……我收回了我对是一个问题,投票决定关闭另一个。@AlexanderVogt是正确的,下面的答案是正确的,但不属于这个问题,而属于另一个缺少Fortran代码的问题。有一些编译器警告应该会有所帮助。我不记得它们是如何包含在
    -Wall
    中的(我不记得具体的标志)。我尝试了
    -Wconversion
    ,但没有收到任何警告:([我总是启用
    -Wall-Wextra-g-fbacktrace
    ]我的意思是
    -Wconversio