Получите numpy, чтобы предупредить о целочисленном переполнении

В основном используя python, я избалован тем, что мне не нужно беспокоиться о целочисленном переполнении. Теперь, когда я использую numpy, мне снова приходится об этом беспокоиться. Я хотел бы, чтобы numpy ошибался в случаях переполнения, но, похоже, это не работает для int64.

import numpy
numpy.seterr(all='raise')
print("{:,}".format(numpy.prod([10]*50)))
# -5,376,172,055,173,529,600
print("{:,}".format(numpy.int64(3200000000) * numpy.int64(3200000000)))
# -8,206,744,073,709,551,616
print("{:,}".format(numpy.int32(320000) * numpy.int32(320000)))
# FloatingPointError: overflow encountered in int_scalars -- Finally getting an error!

Я всегда мог бы добавить dtype=object, чтобы исправить эти проблемы, но я думаю, что int64 достаточно хорош в большинстве случаев, просто страшно, что он может выйти из строя таким трудно обнаруживаемым способом.

Почему seterr работает только для int32? Могу ли я заставить его работать для int64?

Единственная часть документов numpy.seterr, которую я можно найти, что может намекнуть на то, почему это может быть так, следующий короткий отрывок:

Обратите внимание, что операции над целочисленными скалярными типами (например, int16) обрабатываются как с плавающей запятой, и на них влияют эти настройки.

Но ничто в документах типа данных не предполагает, что int32 и int64 как-то концептуально разные. Не уверен, что int64 не считается «целочисленным скалярным типом».


person Dan    schedule 14.08.2015    source источник
comment
Похоже на пустую ошибку; см. github.com/numpy/numpy/pull/3199 . Как ни странно, print(numpy.int64(2**63-1) * numpy.int64(2)) вызывает исключение в моей системе (Ubuntu 14.04, Python 2.7.6, numpy 1.8. 2), но ваш пример показывает ошибочное поведение.   -  person Rory Yorke    schedule 15.08.2015
comment
Этот комментарий должен быть опубликован как ответ, и он должен быть принятым ответом.   -  person David Parks    schedule 11.08.2019


Ответы (1)


Действительно, похоже, что поведение зависит от размера типа int. Вот список, который включает ваш случай и добавляет еще несколько (установив numpy.seterr(all='raise')).

In [25]: numpy.int(3200000000) * numpy.int(3200000000)
Out[25]: 10240000000000000000

In [26]: numpy.int8(3200000000) * numpy.int8(3200000000)
Out[26]: 0

In [27]: numpy.int16(3200000000) * numpy.int16(3200000000)
---------------------------------------------------------------------------
FloatingPointError                        Traceback (most recent call last)
<ipython-input-27-a6185c9da0fd> in <module>()
----> 1 numpy.int16(3200000000) * numpy.int16(3200000000)

FloatingPointError: overflow encountered in short_scalars

In [28]: numpy.int32(3200000000) * numpy.int32(3200000000)
---------------------------------------------------------------------------
FloatingPointError                        Traceback (most recent call last)
<ipython-input-28-a3909399b44a> in <module>()
----> 1 numpy.int32(3200000000) * numpy.int32(3200000000)

FloatingPointError: overflow encountered in int_scalars

In [29]: numpy.int64(3200000000) * numpy.int64(3200000000)
Out[29]: -8206744073709551616
person Ramon Crehuet    schedule 11.01.2016