Відповіді:
Ви все ще можете отримати не-число (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
значення мовчки впорскується в свої розрахунки.
**
здається, невдалий баггі. Коли він переповнюється з речовими числами, він видає помилку, але коли який - або з її операндів inf
або -inf
вона повертає або 0.0
або inf
. Так що робить роботу правильно , коли вхід inifinty, але не тоді , коли результат повинен бути нескінченність.
Реалізація мови 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
, ви повинні вручну перевірити знак , якщо ви не хочете , щоб це було правдою.
-1 * float('infinity') == -inf
Так само і C99 .
Представлення IEEE 754 з плаваючою комою, яке використовується всіма сучасними процесорами, має кілька спеціальних бітових шаблонів, зарезервованих для позитивної нескінченності (знак = 0, exp = ~ 0, frac = 0), негативної нескінченності (знак = 1, exp = ~ 0, frac = 0 ), і багато NaN (не число: exp = ~ 0, frac ≠ 0).
Все, про що потрібно турбуватися: деякі арифметики можуть спричинити винятки / пастки з плаваючою комою, але вони не обмежуються лише цими "цікавими" константами.
OverflowError
.
Я знайшов застереження, про яке ніхто досі не згадував. Я не знаю, чи часто це траплятиметься в практичних ситуаціях, але ось це заради повноти.
Зазвичай, обчислення числа модуля нескінченності повертає себе як поплавок, але частка модульної нескінченності повертається 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 .
ДУЖЕ БАГИЙ КАВАТ: Відділення за нулем
в 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
так що будьте обережні!
1e309
буде інтерпретуватися як+inf
і-1e309
буде інтерпретуватися як-inf
.