x**0.5 和 math.sqrt(x) 哪个更精确?
我最近发现,在Python中,x**.5
和math.sqrt(x)
这两种计算方式并不总是得到相同的结果:
Python 2.6.1 (r261:67517, Dec 4 2008, 16:51:00) [MSC v.1500 32 bit (Intel)]
on win32
>>> 8885558**.5 - math.sqrt(8885558)
-4.5474735088646412e-13
在检查所有小于10的7次方的整数时,这两种方法几乎有0.1%的样本结果是不同的,而且随着数字变大,错误的大小会慢慢增加。
所以问题是,哪种方法更准确呢?
9 个回答
7
使用 decimal
可以找到更精确的平方根:
>>> import decimal
>>> decimal.getcontext().prec = 60
>>> decimal.Decimal(8885558).sqrt()
Decimal("2980.86531061032678789963529280900544861029083861907705317042")
11
其实,pow
函数和math.sqrt()
函数都能算出比默认的浮点数类型更精确的结果。我觉得你看到的那些误差,主要是因为浮点数运算本身的局限性,而不是这些函数不准确。而且,计算一个七位数的平方根时,差个大约10的负13次方的数值,真的算不了什么。即使是最精确的物理计算,也很少需要那么多有效数字……
另外,使用math.sqrt()
的一个好处是,它更容易阅读和理解,这通常也是选择某种方式的一个好理由。
26
这两者的准确性没有高低之分,它们都在同样的程度上偏离了实际答案:
>>> (8885558**0.5)**2
8885557.9999999981
>>> sqrt(8885558)**2
8885558.0000000019
>>> 2**1023.99999999999
1.7976931348498497e+308
>>> (sqrt(2**1023.99999999999))**2
1.7976931348498495e+308
>>> ((2**1023.99999999999)**0.5)**2
1.7976931348498499e+308
>>> ((2**1023.99999999999)**0.5)**2 - 2**1023.99999999999
1.9958403095347198e+292
>>> (sqrt(2**1023.99999999999))**2 - 2**1023.99999999999
-1.9958403095347198e+292
http://mail.python.org/pipermail/python-list/2003-November/238546.html
数学模块其实是对平台上C语言库中同名数学函数的封装;
math.pow()
在你需要(或者想要)和C扩展保持高度兼容时最有用,因为它调用的是C语言的pow()
。
__builtin__.pow()
是Python中**
运算符的实现,它可以处理复杂数、无限大的整数次方,以及模幂运算(而C语言的pow()
则不支持这些)。
**
运算符更全面一些。math.sqrt
可能只是C语言中平方根函数的实现,这个函数可能和pow
有关。