Math.pow vs **在Python中作为Decimal运行?

时间:2017-07-18 04:49:03

标签: python

所以我写了一个简单的脚本来演示几何系列的收敛。

from decimal import *
import math
initial = int(input("a1? "))
r = Decimal(input("r? "))
runtime = int(input("iterations? "))

sum_value=0
for i in range(runtime):
   sum_value+=Decimal(initial * math.pow(r,i))
   print(sum_value)

当我使用以下值时:

a1 = 1
r = .2
iterations = 100000

我认为收敛为1.250000000000000021179302083

当我更换线路时:

sum_value+=Decimal(initial * math.pow(r,i))

使用:

sum_value+=Decimal(initial * r ** i)

我得到了更准确的值,1.250000000000000000000000002

这到底有什么区别?根据我的理解,它与math.pow是浮点运算有关,但我只是认为**是数学幂函数的语法糖。如果它们确实不同,那么在将以下内容输入IDLE时,为什么精度值为200:

>>> Decimal(.8**500)
Decimal('3.50746621104350087215129555150772856244326043764431058846880005304485310211166734705824986213804838358790165633656170035364028902957755917668691836297512054443359375E-49')
>>> Decimal(math.pow(.8,500))
Decimal('3.50746621104350087215129555150772856244326043764431058846880005304485310211166734705824986213804838358790165633656170035364028902957755917668691836297512054443359375E-49')

他们似乎完全一样。这里发生了什么?

1 个答案:

答案 0 :(得分:1)

正如您所暗示的那样,差异在于math.pow()将输入转换为float,如the documentation中所述:"与内置**运算符不同,数学.pow()将其参数转换为float类型。"

因此,math.pow()也会提供float作为答案,与输入是Decimal(或int)还是其他任何内容无关。当使用不完全可以表示为float的数字(但是Decimal)时,您可能会使用**运算符获得更精确的答案。

这解释了为什么你的循环在使用**的情况下会提供更精确的结果,因为你正在使用Decimal数字提升到一个整数。在第二种情况下,您无意中将float用于两个计算,然后在已执行操作时将结果转换为Decimal。如果您使用明确的Decimal值,则会看到差异:

>>> Decimal('.8')**500
Decimal('3.507466211043403874762758796E-49')
>>> Decimal(math.pow(Decimal('.8'), 500))
Decimal('3.50746621104350087215129555150772856244326043764431058846880005304485310211166734705824986213804838358790165633656170035364028902957755917668691836297512054443359375E-49')

因此,在第二种情况下,Decimal值会自动转换为float,结果与上面的示例相同。但是,在第一种情况下,计算在Decimal域中执行,结果略有不同。