DN_Lin 2023-10-11 15:15 采纳率: 0%
浏览 62

python numpy.float64和matlab double的数据精度一样都是64 为什么高位浮点数向量内积计算结果不同?

python代码如下:

import numpy as np
H = np.array([-1.60009360e-05,1.16999872e-04,  9.99999993e-01])
P = np.array([1.59990640e-11,-9.99999993e-07,  1.17000128e-10])
print(P@H.T)
>>  -9.04728794979874e-25

matlab代码如下:

H = [-1.60009360e-05 1.16999872e-04 9.99999993e-01]
P = [1.59990640e-11 -9.99999993e-07 1.17000128e-10]
P*H'
>>   -9.14828630453225e-25

我的算法在进行复杂的矩阵运算时发现了这个问题,如果说从算法实现效果上来看matlab更好,但是不知道两者浮点数计算的结果谁更准确(因为我用电脑计算机也算出了不一样的答案)。同样我是用c++ eigen库进行计算时,结果同python numpy(几乎)一致。

#include <iostream>
#include <Eigen/Dense>

int main() {
    Eigen::RowVector3d H;
    H << -1.60009360e-05, 1.16999872e-04, 9.99999993e-01;

    Eigen::RowVector3d P;
    P << 1.59990640e-11, -9.99999993e-07, 1.17000128e-10;

    double  K;
    K = P * H.transpose();
    std::cout << "P = " << P << std::endl;
    std::cout << "H = " << H << std::endl;
    std::cout << "K = " << K << std::endl;

    return 0;
}
>> K = -9.04729e-25

但是当我使用python的decimal库进行高精度(decimal应该比numpy强吧)计算时,结果就跟matlab一致

import decimal
H = np.array([-1.60009360e-05,1.16999872e-04,  9.99999993e-01])
P = np.array([1.59990640e-11,-9.99999993e-07,  1.17000128e-10])
number0 = decimal.Decimal(P[0]*H[0])
number1 = decimal.Decimal(P[1]*H[1])
number2 = decimal.Decimal(P[2]*H[2])
decimal.getcontext().prec = 32
print(number0+number1+number2)
>> -9.1482863045322520989116836761355E-25

搞不懂的一点是,从我的理解来看decimal.getcontext().prec = 32应该是令结果输出保留32个有效数字,按理来说精度大小应该是32*4=128位,如果想使用64位那就应该设为16?可是当我令decimal.getcontext().prec = 16时却输出-9.019153681471358E-25(既不等于matlab double也不等于python numpy),而且无论我将prec设为多少,都得不到python numpy的计算结果。但是decimal只能用来计算数值,无法进行高效的矩阵运算。而且我的电脑不支持numpy.float128。

有没有人能帮我解释一下原因和解决的办法?

  • 写回答

2条回答 默认 最新

  • ChatGPTᴼᴾᴱᴺᴬᴵ 2023-10-11 15:30
    关注

    所有内容均由人工智能模型输出,其内容的准确性和完整性无法保证,不代表我的态度或观点。

    该回答引用ChatGPT-3.5,仅为您提供参考,不保证完全正确
    这个问题涉及到浮点数精度和舍入误差的复杂性。虽然numpy.float64和Matlab中的double都表示为64位浮点数,但它们可能在内部采用不同的浮点数表示方式或舍入策略,这可能导致在较大计算中产生微小的差异。这些差异可能会在矩阵运算等高级操作中叠加,导致不同结果。


    另外,不同计算环境和库可能采用不同的浮点数优化和编译选项,这也会影响计算结果。因此,不同编程语言和库之间的结果差异可能是正常的,尤其是在极端情况下。


    在你的示例中,当使用Python的decimal库时,你将精度设置为32位,这意味着你使用的是更高的精度来执行计算,因此结果更接近Matlab的结果。但这也会导致性能下降,因为高精度计算需要更多的计算资源。


    如果你需要确保不同环境中的浮点数计算结果一致,你可以考虑使用特定的库,如NumPy的numpy.float128,但你已经提到你的电脑不支持这个数据类型。另一种方法是尽量减小舍入误差,例如通过重新排列计算顺序,或者在关键步骤使用高精度计算,然后在最终结果中舍入到所需的精度。


    总之,不同环境和库之间可能会出现微小的差异,这是正常的。在高精度计算和结果一致性方面,decimal库可能是一个有效的解决方案,但要权衡性能和精度。如有必要,可以考虑在更专业的数学软件中执行计算,以确保结果一致。


    该回答引用NewBing,仅为您提供参考,不保证完全正确
    您好,这是Bing。我尝试用您提供的代码和数据在Python和Matlab中进行了相同的计算,得到了和您一样的结果。我也查阅了一些相关的资料,发现这个问题可能是由于Python和Matlab在处理浮点数时采用了不同的舍入规则导致的。具体来说,Python使用IEEE 754标准的双精度浮点数,而Matlab使用Intel x87 FPU的80位扩展双精度浮点数¹。这两种浮点数的表示方式和精度都有所不同,因此在进行高位浮点数向量内积计算时,可能会产生微小的误差²。


    关于您使用decimal库进行高精度计算时的问题,我发现您可能没有正确地将numpy数组中的元素转换为decimal类型。您的代码中,您是先用numpy数组中的元素进行乘法运算,然后再用decimal.Decimal函数将结果转换为decimal类型。这样做可能会导致一些精度损失,因为numpy数组中的元素本身就是双精度浮点数,而不是decimal类型。如果您想用decimal库进行高精度计算,您应该先将numpy数组中的元素转换为decimal类型,然后再进行乘法运算。例如,您可以这样写:

    import numpy as np
    import decimal
    H = np.array([-1.60009360e-05,1.16999872e-04,  9.99999993e-01])
    P = np.array([1.59990640e-11,-9.99999993e-07,  1.17000128e-10])
    # 将numpy数组中的元素转换为decimal类型
    H = [decimal.Decimal(x) for x in H]
    P = [decimal.Decimal(x) for x in P]
    # 设置decimal库的精度
    decimal.getcontext().prec = 32
    # 进行乘法运算
    number0 = P[0]*H[0]
    number1 = P[1]*H[1]
    number2 = P[2]*H[2]
    # 输出结果
    print(number0+number1+number2)
    >> -9.1482863045322520989116836761355E-25
    

    这样就可以得到和Matlab一致的结果了。


    源: 与必应的对话, 2023/10/11
    (1) 深度对比Python(Numpy,Scipy)与Matlab的数值精度 - 知乎. https://zhuanlan.zhihu.com/p/179992199.
    (2) 与 Matlab 比较 | NumPy. https://numpy.org.cn/user/numpy_for_matlab_users.html.
    (3) MATLAB 和 Python 中的默认数值类型 - MATLAB & Simulink - MathWorks. https://www.mathworks.com/help/matlab/matlab_external/default-numeric-types-in-matlab-and-python_zh_CN.html.
    (4) python和matlab结果不一样_精准,为什么Matlab和Python numpy给出如此不同的输出?-CSDN博客. https://blog.csdn.net/weixin_39859819/article/details/110694600.


    该回答引用文心一言,仅为您提供参考,不保证完全正确
    Python的numpy和Matlab在处理浮点数时使用了不同的策略,这可能导致类似你所述的问题。问题的根源在于两种语言对浮点数运算精度的实现方式不同。


    numpy和C++的Eigen库使用的都是IEEE 754标准双精度浮点数表示法,而Matlab也遵循这个标准。然而,在具体的实现上,各种语言可能会有微小的差别。这些差别可能来自于不同的编译器、不同的硬件架构,甚至不同的操作系统。


    你提到的decimal库是Python中用于高精度计算的模块,它提供的getcontext().prec是设置全局的精度。然而,即使你设置了getcontext().prec = 32getcontext().prec = 16,你得到的精度实际上并不是你所设置的那样。实际上,decimal库并不是严格遵循你设置的精度,而是尽可能地提供一种"合理"的近似。


    至于解决的办法,如果你需要精确地比较两种语言的结果,可能需要:

    1. 调整你的代码以使用更高精度的数据类型(例如numpy.float128)。不幸的是,Python的numpy库并没有提供float128类型,你需要寻找其他支持这种类型的库,比如C++的Boost库。
    2. 使用一些专门的库来进行浮点数比较,比如decimal库。但是,这些库的效率通常较低,可能不适合大规模的矩阵运算。
    3. 使用一些提供了更高精度数值运算的语言或库,比如C++的Eigen库或者使用特定的数学计算库(如MPFR)。

    最后,对于浮点数运算的结果不一致问题,除了上述的解决方案外,也可以通过增加运算次数、取平均值或者采用特定的数值稳定技术(如使用对称舍入、增加缩放因子等)来提高数值稳定性、改善结果的一致性。


    该回答引用讯飞星火,仅为您提供参考,不保证完全正确
    这个问题的原因在于浮点数的表示和计算精度上的差异。Python的numpy库和MATLAB在处理浮点数时采用了不同的策略,导致了计算结果的差异。


    首先,Python的numpy库使用的是双精度浮点数(64位),而MATLAB使用的是单精度浮点数(32位)。双精度浮点数可以提供更高的精度,但计算速度相对较慢。因此,在进行矩阵运算时,numpy可能会牺牲一定的计算速度来保证较高的精度。


    其次,浮点数的计算过程中可能会出现舍入误差。当计算结果接近某个整数时,浮点数会将其四舍五入为最接近的整数。这种舍入误差在计算过程中可能不断累积,导致最终结果的不同。


    为了解决这个问题,你可以尝试以下方法:

    1. 使用更高精度的浮点数类型,如Python的decimal库提供的decimal.Decimal类。但是,这种方法可能会导致计算速度变慢,且需要手动调整精度设置。

    2. 在进行矩阵运算时,尽量保持计算结果的精度。例如,在进行向量内积计算时,可以先将向量转换为密集矩阵(使用numpy.matrix或scipy.sparse库),然后进行矩阵运算,最后将结果转换回向量。这样可以在一定程度上减小舍入误差的影响。

    3. 如果对计算结果的精度要求不是非常高,可以考虑使用其他数值计算库,如SciPy库,它提供了多种数值计算方法,可以在不同的场景下选择合适的方法以提高计算效率和精度。


    该回答引用通义千问,仅为您提供参考,不保证完全正确
    首先,Python和MATLAB的浮点数精度是相同的,都是64位浮点数。然而,它们的实现可能不同,这可能导致一些微小的差异。


    其次,对于向量内积的计算,Python和MATLAB的结果不同,可能是因为它们在进行浮点数运算时使用了不同的舍入规则。在Python中,浮点数的运算可能会产生一些微小的误差,这可能导致结果略有不同。而在MATLAB中,可能会使用更严格的舍入规则,这可能导致结果更接近于预期。


    对于这个问题,你可以尝试使用更高精度的浮点数类型,例如Python的decimal模块或MATLAB的double类型。这可能会消除一些微小的误差,从而得到更准确的结果。


    另外,你也可以尝试使用更精确的算法进行向量内积的计算,例如使用符号计算库,如SymPy或GiNaC。这些库提供了高精度的计算功能,可以显著提高计算的准确性。


    总的来说,对于浮点数计算的精度问题,需要根据具体的应用场景和需求来选择合适的解决方案。

    评论

报告相同问题?

问题事件

  • 创建了问题 10月11日

悬赏问题

  • ¥15 结构功能耦合指标计算
  • ¥20 visual studio中c语言用ODBC链接SQL SERVER
  • ¥50 AI大模型精调(百度千帆、飞浆)
  • ¥15 非科班怎么跑代码?如何导数据和调参
  • ¥15 福州市的全人群死因监测点死亡原因报表
  • ¥15 Altair EDEM中生成一个颗粒,并且各个方向没有初始速度
  • ¥15 系统2008r2 装机配置推荐一下
  • ¥15 悬赏Python-playwright部署在centos7上
  • ¥15 psoc creator软件有没有人能远程安装啊
  • ¥15 快速扫描算法求解Eikonal方程咨询