Python Infinity - Будь-які застереження?


179

Отже, Python має позитивну та негативну нескінченність:

float("inf"), float("-inf")

Це просто здається типом функції, яка повинна мати певний застереження. Чи є щось, про що я маю знати?


25
Зауважте, що константа 1e309буде інтерпретуватися як +infі -1e309буде інтерпретуватися як -inf.
Кріс Тейлор

Відповіді:


97

Ви все ще можете отримати не-число (NaN) з простої арифметики, що включає inf:

>>> 0 * float("inf")
nan

Зауважте, що зазвичай ви не отримаєте infзначення за допомогою звичайних арифметичних обчислень:

>>> 2.0**2
4.0
>>> _**2
16.0
>>> _**2
256.0
>>> _**2
65536.0
>>> _**2
4294967296.0
>>> _**2
1.8446744073709552e+19
>>> _**2
3.4028236692093846e+38
>>> _**2
1.157920892373162e+77
>>> _**2
1.3407807929942597e+154
>>> _**2
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
OverflowError: (34, 'Numerical result out of range')

infЗначення вважається дуже особливим значенням з незвичайною семантикою, так що краще знати про OverflowErrorодразу через виключення, а не має infзначення мовчки впорскується в свої розрахунки.


8
Просте додавання, множення тощо поплавця з радістю призведе до інф, хоча: f = 1.3407807929942597e + 154; f * f => інф. Це, швидше за все, виняток **, щоб підняти OverflowError.
ерегон

@eregon, насправді, **здається, невдалий баггі. Коли він переповнюється з речовими числами, він видає помилку, але коли який - або з її операндів infабо -infвона повертає або 0.0або inf. Так що робить роботу правильно , коли вхід inifinty, але не тоді , коли результат повинен бути нескінченність.
Абель

2
@Abel Це не баггі. Переповнення означає, що кількість дуже велика. Занадто великий, щоб його представляти, але все ж набагато менший, ніж нескінченність. Введення нескінченності в таке місце може бути корисним для обробника винятків вашої конкретної логіки програми, але було б неправильно для Python взагалі.
Lutz Prechelt

6
@Lutz, якщо це придумується як множення, це все-таки непослідовна поведінка. Безумовно, великий * великий також не є нескінченним.
Річард Раст

100

Реалізація мови Python слід стандарту IEEE-754 , дуже добре, що ви можете використовувати в якості керівництва, але вона спирається на основній системі він був складений на, так відмінність платформи може статися. Останнім часом¹ було застосовано виправлення, яке дозволяє «нескінченність», а також «inf» , але це тут має незначне значення.

Наступні розділи однаково добре стосуються будь-якої мови, яка правильно реалізує арифметику з плаваючою точкою IEEE, вона не характерна лише для Python.

Порівняння нерівності

При роботі з нескінченністю та операторами, що перевищують більшу >чи меншу <кількість, враховується наступне:

  • будь-яке число в тому числі +infперевищує-inf
  • будь-яке число, в тому числі -inf, нижче+inf
  • +infне є ні вищим, ні нижчим за+inf
  • -inf не є ні вищим, ні нижчим за -inf
  • ні в яке порівняння з участю NaNпомилково ( infні вище, ні нижче , ніж NaN)

Порівняння рівності

Якщо порівнювати рівність, +infі +infвони рівні, як -infі -inf. Це дуже дискусійне питання і може здатися вам суперечливим, але це в стандарті IEEE і Python поводиться просто так.

Звичайно, +infвона нерівна -infі все, включаючи NaNсебе, нерівне NaN.

Розрахунки з нескінченністю

Більшість обчислень з нескінченністю дасть нескінченність, якщо тільки обидва операнди не є нескінченними, коли ділення операції або модуль, або при множенні на нуль, є деякі спеціальні правила, які слід пам’ятати:

  • при множенні на нуль, для якого результат не визначений, він дає результат NaN
  • при поділі будь-якого числа (крім самої нескінченності) на нескінченність, що поступається 0.0або -0.0².
  • при поділі (включаючи модуль) позитивну або негативну нескінченність на позитивну або негативну нескінченність результат не визначений, так NaN.
  • при відніманні результати можуть бути дивовижними, але дотримуйтесь здорового математичного сенсу :
    • при виконанні inf - inf, то результат не визначений: NaN;
    • коли робиш inf - -inf, результат є inf;
    • коли робиш -inf - inf, результат є -inf;
    • при виконанні -inf - -inf, то результат не визначений: NaN.
  • додаючи, це також може бути дивно:
    • коли робиш inf + inf, результат є inf;
    • при виконанні inf + -inf, то результат не визначений: NaN;
    • при виконанні -inf + inf, то результат не визначений: NaN;
    • коли робиш -inf + -inf, результат є -inf.
  • використовуючи math.pow, powабо **складно, так як вона не поводиться , як це повинно бути. Він кидає виняток переповнення , коли результат з двома числами занадто високий , щоб відповідати подвійної точності з плаваючою точкою (вона повинна повертати нескінченність), але коли вхід infабо -infвін веде себе правильно і повертає або infабо 0.0. Коли другий аргумент є NaN, він повертається NaN, якщо не є перший аргумент 1.0. Існує більше питань, не всі висвітлені в документах .
  • math.expстраждає від тих же питань, що і math.pow. Рішенням, щоб виправити це для переповнення, є використання аналогічного цьому коду:

    try:
        res = math.exp(420000)
    except OverflowError:
        res = float('inf')

Примітки

Примітка 1: як додатковий застереження, що, як визначено стандартом IEEE, якщо результат обчислення є недостатнім або переливним, результат буде не помилкою перевантаження або переливу, а позитивною чи негативною нескінченністю: 1e308 * 10.0врожайність inf.

Примітка 2: оскільки будь-який обчислення із NaNповерненнями NaNта будь-яке порівняння NaN, включаючи NaNсаме себе false, слід скористатися math.isnanфункцією, щоб визначити, чи дійсно число NaN.

Примітка 3: хоча Python підтримує запис float('-NaN'), цей знак ігнорується, оскільки немає NaNвнутрішнього знаку . Якщо розділити -inf / +inf, результат є NaN, ні -NaN(немає такого).

Примітка 4: будьте обережні, покладайтеся на будь-що з вищезазначеного, оскільки Python покладається на бібліотеку C або Java, для якої вона була складена, і не всі базові системи правильно реалізують цю поведінку. Якщо ви хочете бути впевнені, протестуйте на нескінченність, перш ніж робити свої розрахунки.

¹) Останнім часом означає з версії 3.2 .
²) Плаваючі точки підтримують позитивний та негативний нуль, тому: x / float('inf')зберігає свій знак і -1 / float('inf')врожайність -0.0, 1 / float(-inf)врожайність -0.0, 1 / float('inf')урожайність 0.0та -1/ float(-inf)врожайність 0.0. Крім того, 0.0 == -0.0цеtrue , ви повинні вручну перевірити знак , якщо ви не хочете , щоб це було правдою.


11
Невеликий нітпік: не кожен розрахунок з нескінченністю приносить нескінченність:-1 * float('infinity') == -inf
Еван Кралл

4
Ось чому я сказав, що це була маленька гвоздика. Ви хвилювали мене на хвилину, що цей знак буде повністю ігнорований при роботі з нескінченністю, і я хотів уточнити для інших людей.
Еван Кралл

12
Ну, майже: 1 / float ('нескінченність') == 0,0
Phil

3
@Phil: Хоча я впевнений, що ви просто намагалися показати, що не всі обчислення з inf призводять до inf або NaN, я просто хотів дати зрозуміти іншим, хто може читати через коментарі, що 1 / float ('нескінченність ') == 0,0 вірно; бо, коли ви наближаєтесь до нескінченності, результат поділу наближається до 0. Я знаю, що це просто основне обчислення, але я хотів бути впевненим, що ті, хто читає, розуміють або, принаймні, мають поняття, чому це результат.
Ентоні Пейс

1
У мене таке відчуття, що ця відповідь набагато краща за прийняту відповідь.
Крістіан Геренц

3

Так само і C99 .

Представлення IEEE 754 з плаваючою комою, яке використовується всіма сучасними процесорами, має кілька спеціальних бітових шаблонів, зарезервованих для позитивної нескінченності (знак = 0, exp = ~ 0, frac = 0), негативної нескінченності (знак = 1, exp = ~ 0, frac = 0 ), і багато NaN (не число: exp = ~ 0, frac ≠ 0).

Все, про що потрібно турбуватися: деякі арифметики можуть спричинити винятки / пастки з плаваючою комою, але вони не обмежуються лише цими "цікавими" константами.


1
Тож якщо моя арифметика занадто велика, це може стати інф?
Casebash

@Casebash Ні, це призведе до OverflowError.
wizzwizz4

2

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

Зазвичай, обчислення числа модуля нескінченності повертає себе як поплавок, але частка модульної нескінченності повертається nan(не число). Ось приклад:

>>> from fractions import Fraction
>>> from math import inf
>>> 3 % inf
3.0
>>> 3.5 % inf
3.5
>>> Fraction('1/3') % inf
nan

Я подав проблему на трекер помилок Python. Його можна побачити на https://bugs.python.org/issue32968 .

Оновлення: це буде виправлено в Python 3.8 .


2

ДУЖЕ БАГИЙ КАВАТ: Відділення за нулем

в 1/xчастці, до x = 1e-323цього є, infале коли x = 1e-324або мало він кидаєZeroDivisionError

>>> 1/1e-323
inf

>>> 1/1e-324
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: float division by zero

так що будьте обережні!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.