哪个更准确,x**.5还是math.sqrt(x)?

Ben*_*ank 22 python floating-point

我最近发现x**.5并且math.sqrt(x)并不总是在Python中产生相同的结果:

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
Run Code Online (Sandbox Code Playgroud)

检查低于10**7的所有整数,这两种方法对几乎正好0.1%的样本产生不同的结果,对于较大的数字,误差的大小增加(缓慢).

所以问题是,哪种方法更准确?

Unk*_*own 25

两者都不是更准确,它们都是等分的实际答案:

>>> (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
Run Code Online (Sandbox Code Playgroud)

http://mail.python.org/pipermail/python-list/2003-November/238546.html

math模块包装了相同名称的平台C库数学函数; math.pow()如果你需要(或只是想)与调用C的C扩展的高兼容性,它是最有用的pow().

__builtin__.pow()是Python的中缀** 运算符的实现,并且处理复数,无界整数幂和模幂运算(C pow()不处理任何这些).

**更完整.math.sqrt可能只是sqrt的C实现,可能与之相关pow.

  • `sqrt`是IEEE 754定义的基本操作之一.它应该直接实现,而不是作为对`pow`的调用,并且作为基本操作它应该具有正确的舍入(通常的`pow`实现没有, 不是由一个长镜头). (9认同)
  • 以与幂/平方根**相同的精度计算浮点中的(8885558**0.5)`和`sqrt(8885558)`**的相应平方并期望该计算告诉任何关于哪个结果更多的结果准确是天真的.得出的结论是"它们都与实际答案相等"是可笑的:它们以浮点计算的正方形与1ULP的8885558.0不同. (5认同)

Emi*_*l H 11

pow函数和math.sqrt()函数都可以计算比默认浮点类型可以存储的结果更准确的结果.我认为您看到的错误是浮点数学的局限性而不是函数的不准确性的结果.另外,因为当取7位数的平方根时,差异是~10 ^( - 13)?即使是最精确的物理计算也很少需要许多有效数字......

使用math.sqrt()的另一个原因是它更容易阅读和理解,这通常是以某种方式做事的一个很好的理由.


jfs*_*jfs 7

使用decimal找到更精确的平方根:

>>> import decimal
>>> decimal.getcontext().prec = 60
>>> decimal.Decimal(8885558).sqrt()
Decimal("2980.86531061032678789963529280900544861029083861907705317042")
Run Code Online (Sandbox Code Playgroud)