Почему x * * 4.0 быстрее, чем x**4 в Python 3?
почему 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 указал, что это не происходит вне цикла. Я проверил и ситуация возникает только (из того, что я видел), когда базовый становится подняли. Есть идеи по этому поводу?
3 ответа:
почему
x**4.0
быстрее чемx**4
в Python 3*?Python 3
int
объекты - это полноценный объект, предназначенный для поддержки произвольного размера; в связи с этим они обрабатывается как таковой на уровне C (смотрите, как все переменные объявляются какPyLongObject *
типlong_pow
). Это также делает их возведение в степень намного больше хитрее и нудно, так как вам нужно поиграйте сob_digit
массив, который он использует для представления своего значения для его выполнения. (источник для смелых. -- вижу: понимание выделения памяти для больших целых чисел в Python подробнее оPyLongObject
s.)Python
float
объекты, наоборот, может быть преобразован доdouble
тип (с помощьюPyFloat_AsDouble
) и операции могут быть выполнены используя эти собственные типы. это отлично потому что, после проверки соответствующих крайних случаев, он позволяет Python использовать платформы'pow
(сpow
, что составляет) для обработки фактического возведения в степень:/* Now iv and iw are finite, iw is nonzero, and iv is * positive and not equal to 1.0. We finally allow * the platform pow to step in and do the rest. */ errno = 0; PyFPE_START_PROTECT("pow", return NULL) ix = pow(iv, iw);
здесь
iv
иiw
наш оригинальныйPyFloatObject
как сdouble
s.для чего это стоит: Python
2.7.13
для меня это фактор2~3
быстрее, и показывает обратное поведение.предыдущей факт также объясняет несоответствие между Python 2 и 3 Итак, я подумал, что я бы тоже обратился к этому комментарию, потому что это интересно.
в Python 2, вы используете старую
int
объект, который отличается от
если мы посмотрим на байт-код, то увидим, что выражения полностью идентичны. Единственное отличие-это тип константы, которая будет аргументом
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
обновление: давайте взглянем на объекты/реферат.c в исходном коде CPython:
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
, который слишком долго, чтобы вставить сюда, так вот ссылка.он называет
nb_power
слотx
, передаетy
в качестве аргумента.наконец, в
float_pow()
в строке 686 от объекты/floatobject.c мы видим, что аргументы преобразуются в Cdouble
прямо перед фактической деятельности: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); ...
потому что одно правильно, другое-приближение.
>>> 334453647687345435634784453567231654765 ** 4.0 1.2512490121794596e+154 >>> 334453647687345435634784453567231654765 ** 4 125124901217945966595797084130108863452053981325370920366144 719991392270482919860036990488994139314813986665699000071678 41534843695972182197917378267300625