浮点数的乘法在 Numpy 和 R 中给出不同的结果

Posted

技术标签:

【中文标题】浮点数的乘法在 Numpy 和 R 中给出不同的结果【英文标题】:Multiplication of floating point numbers gives different results in Numpy and R 【发布时间】:2016-04-15 01:15:31 【问题描述】:

我正在使用 Python (Numpy) 和 R 进行数据分析。我的数据是一个向量 795067 X 3,根据我使用的是 Numpy 还是 R,计算该数据的平均值、中位数、标准差和 IQR 会产生不同的结果. 我交叉检查了这些值,看起来 R 给出了“正确”的值。

Median: 
Numpy:14.948499999999999
R: 14.9632

Mean: 
Numpy: 13.097945407088607
R: 13.10936

Standard Deviation: 
Numpy: 7.3927612774052083
R: 7.390328

IQR: 
Numpy:12.358700000000002
R: 12.3468

两个平台上数据的最大值和最小值相同。我进行了快速测试以更好地了解这里发生了什么。

在 Numpy 中乘以 1.2*1.2 得到 1.4(与 R 相同)。 在 Numpy 中乘以 1.22*1.22 得到 1.4884,在 R 中也是如此。 但是,在 Numpy 中乘以 1.222*1.222 得到 1.4932839999999998,这显然是错误的!在 R 中做乘法给出 1.49324 的正确答案。 在 Numpy 中乘以 1.2222*1.2222 在 R 中得到 1.4937728399999999 和 1.493773。再一次,R 是正确的。

在 Numpy 中,数字是 float64 数据类型,在 R 中它们是双精度数。这是怎么回事?为什么 Numpy 和 R 给出不同的结果?我知道 R 使用 IEEE754 双精度,但我不知道 Numpy 使用什么精度。我怎样才能改变 Numpy 给我“正确”的答案?

【问题讨论】:

这将有助于显示您的代码,以便我们解决您的实际问题。区分浮点是如何打印与实际浮点也很重要。例如,在 R 中,sprintf("%.20f", 1.222*1.222) 打印出 "1.49328399999999983372",这与您在 Python 中得到的 ':.20f'.format(1.222*1.222) 完全相同。浮点值是一样的,但是当你在 R 提示符下输入 1.222*1.222 时,R 打印 1.493284 而 Python 打印 1.4932839999999998 您也可以尝试将 NumPy 数据的dtype 更改为float128data = data.astype(np.float128)。这可能会有所帮助,尽管这只是在没有看到您的 Python 和 R 代码的情况下在黑暗中拍摄。 @unutbu:R 使用 64 位浮点数,因此在 Python 中坚持使用 64 位浮点数在这里是合理的。 尝试将您的数据集缩减为仍然显示出差异的较小数据集。发布你的代码,如果可能的话,减少数据集(如果它很大,你不能在这里粘贴它,所以在别处分享)。 “在 Numpy 中乘以 1.2*1.2 得到 1.4” - 这不是乘法的工作原理! 【参考方案1】:

Python

Python 中的print 语句/函数将打印单精度浮点数。计算实际上将以指定的精度进行。 Python/numpy 默认使用双精度浮点数(至少在我的 64 位机器上):

import numpy

single = numpy.float32(1.222) * numpy.float32(1.222)
double = numpy.float64(1.222) * numpy.float64(1.222)
pyfloat = 1.222 * 1.222

print single, double, pyfloat
# 1.49328 1.493284 1.493284

print "%.16f, %.16f, %.16f"%(single, double, pyfloat)
# 1.4932839870452881, 1.4932839999999998, 1.4932839999999998

在交互式 Python/iPython shell 中,shell 在打印语句结果时会打印双精度结果:

>>> 1.222 * 1.222
1.4932839999999998

In [1]: 1.222 * 1.222
Out[1]: 1.4932839999999998

R

看起来 R 在使用 printsprintf 时与 Python 做的一样:

print(1.222 * 1.222)
# 1.493284

sprintf("%.16f", 1.222 * 1.222)
# "1.4932839999999998"

与交互式 Python shell 相比,交互式 R shell 在打印语句结果时也会打印单精度:

> 1.222 * 1.222
[1] 1.493284

Python 和 R 的区别

结果中的差异可能是由于在 numpy 中使用单精度值造成的。有很多加法/减法的计算最终会使问题浮出水面:

In [1]: import numpy

In [2]: a = numpy.float32(1.222)

In [3]: a*6
Out[3]: 7.3320000171661377

In [4]: a+a+a+a+a+a
Out[4]: 7.3320003

正如 cmets 对您的实际问题所建议的那样,请确保在您的 numpy 计算中使用双精度浮点数。

【讨论】:

以上是关于浮点数的乘法在 Numpy 和 R 中给出不同的结果的主要内容,如果未能解决你的问题,请参考以下文章

js 后端返回浮点数,前端用乘法或者除法处理,得到超常值

尝试连接 keras 模型:ValueError:无法将 NumPy 数组转换为张量(不支持的对象类型浮点数)

[python基础] 浮点数乘法的误差问题

展平 3D NumPy 数组中的内部元组并作为浮点数保存到 CSV

Simd matmul 程序给出不同的数值结果

如何将 int numpy 数组的列乘以浮点数并保持在 int 中?