OverflowError: (34, «Числовой результат вне диапазона») при написании пользовательской реализации pow (x, n) - PullRequest
1 голос
/ 07 мая 2019

При реализации pow (x, n) для (x = 2 и n = -2147483648) я получаю следующую ошибку:

Код:

class Solution:
    def myPow(self, x, n):
        flag = n < 0
        n = -1 * n if flag else n
        ans = None
        if n % 2 == 0:
            t = pow(x, n/2)
            ans = t*t
        else:
            t = pow(x, (n-1)/2)
            ans = x * t * t
        return (1/ans) if flag else ans

if __name__ == "__main__":
    Solution().myPow(2,-2147483648)

Traceback (most recent call last):
  File "pw.py", line 16, in <module>
    Solution().myPow(2,-2147483648)
  File "pw.py", line 8, in myPow
    t = pow(x, n/2)
OverflowError: (34, 'Numerical result out of range')

Однако, когда я реализую то же самое с n / 2 и (n-1) / 2, приведенным к типу int, как показано ниже, фрагмент кода я получаю 0.0 в качестве вывода:

class Solution:
    def myPow(self, x, n):
        flag = n < 0
        n = -1 * n if flag else n
        ans = None
        if n % 2 == 0:
            t = pow(x, int(n/2))
            ans = t*t
        else:
            t = pow(x, int((n-1)/2))
            ans = x * t * t
        return (1/ans) if flag else ans

if __name__ == "__main__":
    Solution().myPow(2,-2147483648)

Я не могу выяснить причину. Это из-за переполнения стека, поскольку интерпретатор python не обрабатывает оптимизацию хвостовой рекурсии, а возвращаемый результат сохраняется, поскольку он используется позже для дальнейших вычислений.

Мне любопытно узнать, почему эти два случая различаются.

Ответы [ 2 ]

3 голосов
/ 07 мая 2019

/ в Python 3.x всегда выполняет деление с плавающей запятой , в отличие от Python 2.x, где операнды должны были явно приводиться. Следовательно, type(n/2) == float, тогда как type(int(n/2)) == int. В качестве альтернативы вы можете использовать n // 2, где // выполняет деление на этаж / целое число.

Встроенная функция pow возвращает float, если один из аргументов также float s. Внутренне это числа с плавающей запятой двойной точности, которые могут хранить до ~ 10 308 - намного меньше, чем 2 2147483648/2 , следовательно, OverflowError.

1 голос
/ 07 мая 2019

Размер значения, возвращаемого после вычисления, слишком велик, чтобы его можно было сохранить даже для переменной с плавающей запятой, и поэтому он выдает ошибку с исключением OverFlowError

...