首先,我不是数学爱好者,所以大数精度很少渗透到我的日常工作中。请温柔点;)
使用 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
,这将是 float32
或 float64
,具体取决于机器的 native 架构。
关于转置矩阵的 Python 32/64 位机器浮点求和不正确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8838924/