如何在Python中使用精确浮点运算



我有这个问题在python与浮点算法。我正在解的方程如下:

-a *((x-m)*110.0*(1-m))**b +a*((x-m)*110.0*(1-m))**c
a is a really large positive number (in the hundred thousands)
b is 1.0000002
c is 0.9999998

当我在excel中这样做时,我得到准确的结果,但当我在python中这样做时,我得到完全不准确的结果。

对于每个单独的部分,结果是完全相同的,直到我乘以-a和a。因此((x-m)110.0(1-m))**b和((x-m)110.0(1-m))**c与它们的excel计算值完全相同,但是当它们乘以较大的数字时,它们完全改变了。

我该怎么做?我必须换一种语言吗?这个问题只存在于python中,还是存在于所有语言中?

编辑:这是完全相同的方程在excel和python。完全一样。在我乘以a和-a之前这些数字都是一样的。他们都相差5个点左右。对于x=0.5和m = 0.265, excel中的答案约为0.47,而python的答案约为-0.67

mpmath可以是答案

Mpmath是一个纯python库多精度浮点算术。它提供了广泛的超越函数的集合,无限的指数大小,复数数字,区间算术,数值积分和分化,寻根,线性代数,以及更多。

http://code.google.com/p/mpmath/

很难理解你正在寻找的精度,但我认为你也可以看看十进制模块。-

相对于浮点数据类型:

Decimal "是基于浮点数的模型是和人一起设计的在心里,必然有一个〇最高指导原则计算机必须提供一种算法这和人们学习的算术学校。——摘自小数算术规范。

可以表示十进制数完全正确。相反,像1.1这样的数字2.2没有确切的二进制浮点表示点。最终用户通常不会期望1.1 + 2.2显示为3.3000000000000003与二进制浮点数相同

的精确性延续到算术。在小数浮点数中,0.1 + 0.1 + 0.1 - 0.3等于零。在二进制浮点数中,结果为5.5511151231257827e-017。虽然接近于零,但差异防止可靠的相等性测试和差异会累积。对于这个原因,十进制优先会计应用程序严格相等不变量。

十进制模块包含a有意义的地方的概念1.30 + 1.20 = 2.50。后面的零被保留以表示重要性。这按惯例的介绍是什么货币的应用程序。为乘法,"教科书"方法中使用了所有的数字被乘数。例如,1.3 * 1.2给出1.56,而1.30 * 1.20给出1.5600 .

根据定义,浮点运算不是完全100%准确的,因为值是用分数表示的。请查看有关Python浮点数限制的文章,以及另一篇更通用的文章。

我尝试使用以下值(我为a选择了十万中的东西,因为这与您的描述一样具体):

>>> a = 500000.0
>>> b = 1.0000002
>>> c = 0.9999998
>>> x = 0.5
>>> m = 0.265

计算内部值:

>>> inner = (x - m) * 110.0 * (1 - m)
>>> print inner
18.99975

和指数:

>>> exponent1 = inner**b
>>> exponent2 = inner**c
>>> print (exponent1, exponent2)
(18.999761188674185, 18.999738811332392)

指数乘以a:

>>> aexp1 = -a * exponent1
>>> aexp2 = a * exponent2
>>> print (aexp1, aexp2)
(-9499880.5943370927, 9499869.4056661967)

和最终答案:

>>> final = aexp1 + aexp2
>>> print final
-11.188670896

这些值在Excel中得到什么?或者,发布你实际使用的a值,我会更新我的答案。

现在,当人们在评论中问你这个问题时,你在某种程度上回避了这个问题,但是如果你想让我们弄清楚为什么在Excel中是不同的,你需要告诉我们确切地你是如何在Excel中进行计算的。这意味着您放入单元格中以生成值的公式。告诉我们它们是完全相同的是没有用的,因为它没有给我们任何继续下去的东西。从这里开始,我的猜测是它们实际上并不相同,因为我认为不太可能出现浮点错误或类似的错误,这将是您在问题中报告的大小错误的原因。更有可能的是你在某个地方打错字或有误解。

如果您只想要任意精度的算术,请使用fractions模块中的Fraction类,它是标准库的一部分。计算完成后,可以将其转换为浮点数(如果必须的话)。不幸的是,最终的浮点数可能不是任意精度,但在转换为浮点数之前的所有计算都将是任意精度,因此您的浮点数可能比您一直使用浮点数更准确。

真的,如果你不在乎视觉效果,只要一直保持数字分数,你的问题就解决了。如果你真的关心小数点,你需要意识到,在这种情况下,任意精度将是一个相当复杂的过程,因为你必须处理重复的值(比如三分之一是一堆永远的三,在0.之后)。尽管如此,还是有人试图解决这个问题。让它精确到某个小数点当然是可能的,但如果你不使用分数,不要期望超过这个。

分数有分子和分母(我相信它们被存储为long, Python中的long已经是任意精度了;所以分子和分母都可以是任意大的数。我编写了一些代码,用于将分数从1234/12样式转换为2 3/4样式。但是,我不想通过在这里发布它来给它一个CC许可(我宁愿一个真正的软件许可,比如MIT)。所以,如果你感兴趣的话,你得让我知道。

以下是如何使用fractions.Fraction的示例:

from fractions import Fraction
x=Fraction("2.234532456345265356356356354624356356235635634563563565635645") #You can add string numbers of any value.
y=Fraction(1, 3234524352345) #This is one 3234524352345th 
x+=5 #adding five (The five doesn't have to be a Fraction object, but the result will be one.)
y=x/y #Dive x by y.
x=float(x) #Converting it into a float

无论如何,你可以像对待其他类型的数字一样对待它们。你可以像转换整数一样将事物转换为分数(例如Fraction(4.2343)将浮点数转换为分数)。也可以四舍五入,或者其他。

我发现分数类的代表远远不足。我经常用它。它真是太棒了。

最新更新