为什么x**4.0
比x**4
快?我使用的是CPython 3.5.2。
$ python -m timeit "for x in range(100):" " x**4.0"
10000 loops, best of 3: 24.2 usec per loop
$ python -m timeit "for x in range(100):" " x**4"
10000 loops, best of 3: 30.6 usec per loop
我试着改变我提升的幂,看看它是如何工作的,例如,如果我将x提升到10或16的幂,它会从30跳到35,但是如果我以浮点数的形式提升10.0,它只是在24.1~4附近移动。
我猜这与浮点数转换和2的幂有关,但我真的不知道。
我注意到,在这两种情况下,2的幂都更快,我猜是因为这些计算对于解释器/计算机来说更本机/更容易。但是,使用浮点时,它几乎不会移动。2.0 => 24.1~4 & 128.0 => 24.1~4
但 2 => 29 & 128 => 62
TigerhawkT3指出,这不会发生在循环之外。我检查了一下,这种情况只发生在(从我所看到的)基础被提升的时候。对此有什么想法吗?
发布于 2017-02-21 06:28:23
如果我们查看字节码,我们可以看到表达式是完全相同的。唯一的区别是作为BINARY_POWER
参数的常量类型。所以可以肯定的是,这是由于int
被转换成了浮点数。
>>> def func(n):
... return n**4
...
>>> def func1(n):
... return n**4.0
...
>>> from dis import dis
>>> dis(func)
2 0 LOAD_FAST 0 (n)
3 LOAD_CONST 1 (4)
6 BINARY_POWER
7 RETURN_VALUE
>>> dis(func1)
2 0 LOAD_FAST 0 (n)
3 LOAD_CONST 1 (4.0)
6 BINARY_POWER
7 RETURN_VALUE
更新:让我们看看CPython源代码中的Objects/abstract.c:
PyObject *
PyNumber_Power(PyObject *v, PyObject *w, PyObject *z)
{
return ternary_op(v, w, z, NB_SLOT(nb_power), "** or pow()");
}
PyNumber_Power
调用ternary_op
,它太长了,不能粘贴到这里,所以here's the link。
它调用x
的nb_power
槽,并将y
作为参数传递。
最后,在float_pow()
中,在Objects/floatobject.c的686行,我们看到参数在实际操作之前被转换为C double
:
static PyObject *
float_pow(PyObject *v, PyObject *w, PyObject *z)
{
double iv, iw, ix;
int negate_result = 0;
if ((PyObject *)z != Py_None) {
PyErr_SetString(PyExc_TypeError, "pow() 3rd argument not "
"allowed unless all arguments are integers");
return NULL;
}
CONVERT_TO_DOUBLE(v, iv);
CONVERT_TO_DOUBLE(w, iw);
...
发布于 2017-09-11 13:18:12
因为一个是正确的,另一个是近似值。
>>> 334453647687345435634784453567231654765 ** 4.0
1.2512490121794596e+154
>>> 334453647687345435634784453567231654765 ** 4
125124901217945966595797084130108863452053981325370920366144
719991392270482919860036990488994139314813986665699000071678
41534843695972182197917378267300625
https://stackoverflow.com/questions/42355194
复制相似问题