为什么乘法的顺序会影响结果?请考虑以下代码
a=47.215419672114173
b=-0.45000000000000007
c=-0.91006620964286644
result1=a*b*c
temp=b*c
result2=a*temp
result1==result2
我们都知道 result1 应该等于 result2 ,但我们得到:
result1==result2 #FALSE!
差异很小
result1-result2 #3.552713678800501e-15
但是,对于特定应用程序,此错误可能会放大,以便执行相同计算的两个程序的输出(一个使用result1,另一个使用result2)可能完全不同。
为什么会如此以及如何在数字/科学应用中解决这些问题呢?
谢谢!
更新
答案很好,但我仍然错过为什么乘法的顺序的原因,例如
temp2=a*b
result3=temp2*c
result1==result3 #True
所以似乎编译器/解释器将* b * c视为(a * b)* c
答案 0 :(得分:9)
将浮点数从十进制表示转换为二进制表示时,所有编程语言都会失去精度。这导致不准确的计算(至少从基础10的角度来看,因为数学实际上是在以二进制表示的浮点值上完成的),包括操作顺序改变结果的情况。大多数语言提供数据结构以维持基本10精度,但代价是性能。在Python中查看Decimal
。
编辑:
在回答您的更新时,并非完全如此。计算机按顺序执行操作,因此当您为它们提供一系列操作时,它们将按顺序逐行执行。除顺序命令处理之外,没有明确的操作顺序。
答案 1 :(得分:6)
每次乘法产生的数字(或位数)是原始数字的两倍,需要进行舍入,以便它适合返回为浮点数分配的空间。重新排列订单时,此舍入可能会更改结果。
答案 2 :(得分:4)
在任何编程语言中使用浮点数时,都会失去精度。你可以:
适应精度损失,并相应地调整相等检查,如下所示:
are_equal = (result1-result2)>0.0001
0.0001(epsilon)是您设定的值。
或者使用python提供的Decimal类,这有点慢。
答案 3 :(得分:3)
浮动比较应该总是(由你)用一个小的epsilon完成,比如10 ^ -10
答案 4 :(得分:1)
我们都知道result1应该等于result2,但我们得到:
不,我们并不都知道。事实上,它们不应该是平等的,这就是它们不相等的原因。
您似乎相信您正在使用实数。你不是 - 你正在使用IEEE浮点表示。他们不遵循相同的公理。他们不是一回事。
操作顺序很重要,因为python会计算每个表达式,从而产生一个浮点数。
答案 5 :(得分:1)
为什么: 可能你的机器/ Python无法处理这么多精度。 请参阅:http://en.wikipedia.org/wiki/Machine_epsilon#Approximation_using_Python
怎么做: 这应该有所帮助:http://packages.python.org/bigfloat/
答案 6 :(得分:1)
在计算机中代表数字是计算机科学的一个重要研究领域。这不仅仅是在python中存在的问题,但是任何编程语言都具有此属性,因为默认情况下执行任意计算的任意计算都太昂贵。
算法的The numerical stability反映了思考数值算法时的一些局限性。如前所述,Decimal被定义为在银行应用程序或可能需要它的任何应用程序中执行精确计算的标准。在python中,这个标准有implementation。
答案 7 :(得分:0)
正如先前的帖子很好地回答的那样,这是编程语言中常见的浮点算术问题。您应该意识到永远不要对float
类型应用完全相等。
进行比较时,可以使用基于给定公差(阈值)进行比较的功能。如果数字足够接近,则应将它们视为相等。像这样:
def isequal_float(x1,x2, tol=10**(-8)):
"""Returns the results of floating point equality, according to a tolerance."""
return abs(x1 - x2)<tol
可以解决问题。如果我没记错的话,确切的容差取决于float
类型是单精度还是双精度,这取决于您使用的语言。
使用这样的功能,您可以轻松地比较计算结果,例如在numpy
中。让我们以下面的示例为例,其中使用两种方式为具有连续变量的数据集计算相关矩阵:pandas
方法pd.DataFrame.corr()
和numpy
函数np.corrcoef()
:
import numpy as np
import seaborn as sns
iris = sns.load_dataset('iris')
iris.drop('species', axis = 1, inplace=True)
# calculate correlation coefficient matrices using two different methods
cor1 = iris.corr().to_numpy()
cor2 = np.corrcoef(iris.transpose())
print(cor1)
print(cor2)
结果似乎相似:
[[ 1. -0.11756978 0.87175378 0.81794113]
[-0.11756978 1. -0.4284401 -0.36612593]
[ 0.87175378 -0.4284401 1. 0.96286543]
[ 0.81794113 -0.36612593 0.96286543 1. ]]
[[ 1. -0.11756978 0.87175378 0.81794113]
[-0.11756978 1. -0.4284401 -0.36612593]
[ 0.87175378 -0.4284401 1. 0.96286543]
[ 0.81794113 -0.36612593 0.96286543 1. ]]
,但是它们完全相等的结果却不一样。这些运算符:
print(cor1 == cor2)
print(np.equal(cor1, cor2))
将主要产生False
个元素结果:
[[ True False False False]
[False False False False]
[False False False False]
[False False False True]]
同样,np.array_equal(cor1, cor2)
也将产生False
。但是,自定义函数可以提供所需的比较:
out = [isequal_float(i,j) for i,j in zip(cor1.reshape(16, ), cor2.reshape(16, ))]
print(out)
[True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True]
注意: numpy
包含.allclose()
函数,用于在numpy数组中执行浮点元素逐元素比较。
print(np.allclose(cor1, cor2))
>>>True