为什么 a**2 != a * a 对于一些花车?
Why is a**2 != a * a for some floats?
$ python --version
Python 2.7.15
$ type test.py
import random
while True:
a = random.uniform(0, 1)
b = a ** 2
c = a * a
if b != c:
print "a = {}".format(a)
print "a ** 2 = {}".format(b)
print "a * a = {}".format(c)
break
$ python test.py
a = 0.145376687586
a ** 2 = 0.0211343812936
a * a = 0.0211343812936
我只能在 Python 的 Windows 版本上重现它 - 准确地说:Python 2.7.15 (v2.7.15:ca079a3ea3, Apr 30 2018, 16:30:26) [MSC v.1500 64 bit (AMD64)] on win32
。在我 Python (Python 2.7.15 (default, May 1 2018, 20:16:04) [GCC 7.3.1 20180406] on linux2
) 的 Arch Linux 盒子安装中,循环似乎没有终止,表明 a**2 = a * a
不变量在那里。
这是怎么回事?我知道 IEEE 浮点数有很多误解和特质(例如,this 没有回答我的问题),但我看不出规范的哪一部分或 [=14= 的哪种实现方式] 可能允许这样做。
解决重复标记问题:这很可能不是直接的 IEEE 浮点数学问题,而是 **
运算符的实现问题。因此,这不是仅询问浮点问题(例如精度或关联性)的问题的重复。
Python 的浮点运算依赖于底层平台。我假设 Python 的 **
运算符使用 pow
实现(在 C 中使用)(由 user2357112 referring to Python 2.7.15 source code 确认)。
一般来说,pow
部分是通过使用对数和指数(的近似值)来实现的。这是必要的,因为 pow
支持非整数参数。 (当然,这种通用实现并不排除对其领域子集的专业化。)
Microsoft 的 pow
实施是出了名的不好。因此,对于 pow(a, 2)
,它返回的结果可能不等于 a*a
.
a ** 2
使用 浮点数 幂函数(就像你可以在标准 C 数学库中找到的那个),它能够将任何数字提升到任何电源。
a * a
只是乘以一次,它更适合这种情况,并且不易出现精度错误,(对于整数更是如此),如a ** 2
会是。
对于浮点 a
,如果你想提升到 5 的幂,使用
a * a * a * a * a
你最好用 a**5
因为重复乘法现在容易出现浮点累加错误,而且速度要慢得多。
当 b
很大时,a ** b
更有趣,因为它更有效率,例如。但是精度可能会有所不同,因为它使用了浮点算法。
$ python --version
Python 2.7.15
$ type test.py
import random
while True:
a = random.uniform(0, 1)
b = a ** 2
c = a * a
if b != c:
print "a = {}".format(a)
print "a ** 2 = {}".format(b)
print "a * a = {}".format(c)
break
$ python test.py
a = 0.145376687586
a ** 2 = 0.0211343812936
a * a = 0.0211343812936
我只能在 Python 的 Windows 版本上重现它 - 准确地说:Python 2.7.15 (v2.7.15:ca079a3ea3, Apr 30 2018, 16:30:26) [MSC v.1500 64 bit (AMD64)] on win32
。在我 Python (Python 2.7.15 (default, May 1 2018, 20:16:04) [GCC 7.3.1 20180406] on linux2
) 的 Arch Linux 盒子安装中,循环似乎没有终止,表明 a**2 = a * a
不变量在那里。
这是怎么回事?我知道 IEEE 浮点数有很多误解和特质(例如,this 没有回答我的问题),但我看不出规范的哪一部分或 [=14= 的哪种实现方式] 可能允许这样做。
解决重复标记问题:这很可能不是直接的 IEEE 浮点数学问题,而是 **
运算符的实现问题。因此,这不是仅询问浮点问题(例如精度或关联性)的问题的重复。
Python 的浮点运算依赖于底层平台。我假设 Python 的 **
运算符使用 pow
实现(在 C 中使用)(由 user2357112 referring to Python 2.7.15 source code 确认)。
一般来说,pow
部分是通过使用对数和指数(的近似值)来实现的。这是必要的,因为 pow
支持非整数参数。 (当然,这种通用实现并不排除对其领域子集的专业化。)
Microsoft 的 pow
实施是出了名的不好。因此,对于 pow(a, 2)
,它返回的结果可能不等于 a*a
.
a ** 2
使用 浮点数 幂函数(就像你可以在标准 C 数学库中找到的那个),它能够将任何数字提升到任何电源。
a * a
只是乘以一次,它更适合这种情况,并且不易出现精度错误,(对于整数更是如此),如a ** 2
会是。
对于浮点 a
,如果你想提升到 5 的幂,使用
a * a * a * a * a
你最好用 a**5
因为重复乘法现在容易出现浮点累加错误,而且速度要慢得多。
b
很大时,a ** b
更有趣,因为它更有效率,例如。但是精度可能会有所不同,因为它使用了浮点算法。