转置矩阵的 Python 32/64 位机器浮点求和不正确?

标签 python math matrix numpy

首先,我不是数学爱好者,所以大数精度很少渗透到我的日常工作中。请温柔点;)

使用 NumPy 生成值除以 1 的矩阵:

>>> m = numpy.matrix([(1.0 / 1000) for x in xrange(1000)]).T
>>> m
matrix[[ 0.001 ],
       [ 0.001 ],
       ...
       [ 0.001 ]])

在使用 Python 2.6 的 64 位 Windows 上,求和很少能达到 1.0。 math.fsum() 处理此矩阵,如果我将矩阵更改为使用较小的数字则不会。

>>> numpy.sum(m)
1.0000000000000007
>>> math.fsum(m)
1.0
>>> sum(m)
matrix([[ 1.]])
>>> float(sum(m))
1.0000000000000007

在使用 Python 2.6 的 32 位 Linux (Ubuntu) 上,求和总是得出 1.0。

>>> numpy.sum(m)
1.0
>>> math.fsum(m)
1.0
>>> sum(m)
matrix([[ 1.]])
>>> float(sum(m))
1.0000000000000007

在评估矩阵总和是否为 1 时,我可以在我的代码中添加一个 epsilon(例如 -epsilon < sum(m) < +epsilon),但我想首先了解造成差异的原因是 Python,如果有更好的方法来正确确定总和。

我的理解是,求和处理数字( float )的机器表示与它们的显示方式不同,并且在求和时,使用内部表示。但是,查看我用来计算总和的 3 种方法并不清楚为什么它们在平台之间完全不同或相同。

正确计算矩阵和的最佳方法是什么?

如果您正在寻找更有趣的矩阵,这个简单的更改将具有更小的矩阵数:

>>> m = numpy.matrix([(1.0 / 999) for x in xrange(999)]).T

在此先感谢您的帮助!

更新 我想我想通了。如果我将存储的值更正为 32 位 float ,则结果与 32 位 Linux 求和匹配。

>>> m = numpy.matrix([(numpy.float32(1.0) / 1000) for x in xrange(1000)]).T
>>> m
matrix[[ 0.001 ],
       [ 0.001 ],
       ...
       [ 0.001 ]])
>>> numpy.sum(m)
1.0

这会将矩阵机器数设置为表示 32 位 float ,而不是我的 Windows 测试中的 64 位 float ,并且会正确求和。为什么 0.001 float 在 32 位和 64 位系统上不等于机器号?如果我试图存储具有很多小数位的非常小的数字,我希望它们会有所不同。

有没有人对此有任何想法?在这种情况下,我应该显式切换到 32 位 float ,还是有 64 位求和方法?还是我要重新添加一个 epsilon?对不起,如果我听起来很蠢,我对意见很感兴趣。谢谢!

最佳答案

这是因为您正在比较 32 位 float 和 64 位 float ,正如您已经发现的那样。

如果您在两台机器上指定 32 位或 64 位数据类型,您将看到相同的结果。

Numpy 的默认 float 据类型(numpy 数组的数字类型)与机器精度相同。这就是您在不同机器上看到不同结果的原因。

例如 32 位版本:

m = numpy.ones(1000, dtype=numpy.float32) / 1000
print repr(m.sum())

和 64 位版本:

m = numpy.ones(1000, dtype=numpy.float64) / 1000
print repr(m.sum())

由于精度不同会有所不同,但您会在不同的机器上看到相同的结果。 (但是,64 位操作在 32 位机器上会慢很多)

如果您只指定 numpy.float,这将是 float32float64,具体取决于机器的 native 架构。

关于转置矩阵的 Python 32/64 位机器浮点求和不正确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8838924/

相关文章:

javascript - 在不使用递归的情况下改进连续范围的子集和算法

math - `IntegralDomain`中的 `numeric-prelude`真的是一个积分域吗?

c - 交替的加号和减号运算符有什么作用?

matrix - Spark RDD 到 Matrix

c - 矩阵定义顺序和内存顺序不一样

python - 解包类似元组的文本文件

python - ModuleNotFoundError : No module named 'com.aspose'

python - 由于需求文件而无法部署数据流模板

java - 如何旋转打包到一维数组中的二维矩阵?

python - 如何从Python的网络浏览器捕获HTTP错误