Когда вы делаете
int(math.pow(14764352724, 6))
вы получаете большое число, возведенное в степень, но используя метод с плавающей запятой, даже если аргументы являются целыми числами. Преобразование в целое число теряет точность (исходный результат - число с плавающей точкой: 1.0358251994780843e+61
)
Когда вы делаете
14764352724**6
вы получаете большое число, возведенное в степень с использованием метода двоичной степени , использующего только целочисленное умножение.
Таким образом, второй результат точен, тогда как первый не
>>> int(math.pow(14764352724,6))
10358251994780842724998096890217137953445700726699419360034816 # wrong
>>> 14764352724**6
10358251994780842575401275783021915748383652186833068257611776 # correct
Давайте попробуем разобрать функции **
и math.pow
:
import dis,math
def test(n):
return n ** 3
def test2(n):
return math.pow(n,3)
dis.dis(test)
dis.dis(test2)
* * Выход тысяча двадцать-один * * одна тысяча двадцать-дв
4 0 LOAD_FAST 0 (n)
3 LOAD_CONST 1 (3)
6 BINARY_POWER
7 RETURN_VALUE
7 0 LOAD_GLOBAL 0 (math)
3 LOAD_ATTR 1 (pow)
6 LOAD_FAST 0 (n)
9 LOAD_CONST 1 (3)
12 CALL_FUNCTION 2 (2 positional, 0 keyword pair)
15 RETURN_VALUE
Как видите, функции не эквивалентны. BINARY_POWER
вызывается в первом случае. Эта функция может точно выполнять целочисленное умножение , когда параметры целочисленные :
BINARY_POWER ()
Реализует TOS = TOS1 ** TOS
Двоичная мощность дает то же значение, что и math.pow
, когда параметры не являются целыми:
>>> 14764352724**6.0
1.0358251994780843e+61
>>> int(14764352724**6.0)
10358251994780842724998096890217137953445700726699419360034816
Примечание: что, вероятно, добавляет к путанице встроенный метод pow
, который отличается от math.pow
(и переопределяется последним при использовании from math import pow
), но эквивалентно **
оператору при использовании без аргумента по модулю:
pow (x, y [, z])
Верните x в степень y; если присутствует z, вернуть x в степень y по модулю z (вычисляется более эффективно, чем pow (x, y)% z). Форма с двумя аргументами pow (x, y) эквивалентна использованию оператора степени : x ** y.