Perhatikan bahwa konstanta 1e309akan ditafsirkan sebagai +infdan -1e309akan ditafsirkan sebagai -inf.
Chris Taylor
Jawaban:
97
Anda masih bisa mendapatkan nilai bukan angka (NaN) dari aritmatika sederhana yang melibatkan inf:
>>>0* float("inf")
nan
Perhatikan bahwa Anda biasanya tidak akan mendapatkan infnilai melalui perhitungan aritmatika biasa:
>>>2.0**24.0>>> _**216.0>>> _**2256.0>>> _**265536.0>>> _**24294967296.0>>> _**21.8446744073709552e+19>>> _**23.4028236692093846e+38>>> _**21.157920892373162e+77>>> _**21.3407807929942597e+154>>> _**2Traceback(most recent call last):File"<stdin>", line 1,in?OverflowError:(34,'Numerical result out of range')
The infnilai dianggap sebagai nilai yang sangat khusus dengan semantik yang tidak biasa, jadi lebih baik untuk mengetahui tentang OverflowErrorlangsung melalui pengecualian, daripada memiliki infnilai diam-diam disuntikkan ke dalam perhitungan Anda.
Tambahan float sederhana, multiplikasi, dll akan dengan senang hati menghasilkan inf meskipun: f = 1.3407807929942597e + 154; f * f => inf. Tampaknya agak pengecualian ** untuk meningkatkan OverflowError.
eregon
@ eregon, sebenarnya, **tampak agak buggy. Ketika meluap dengan angka nyata, ia melempar kesalahan, tetapi ketika salah satu operandnya adalah infatau -inf, ia mengembalikan salah satu 0.0atau inf. Jadi tidak bekerja dengan benar ketika input inifinty, tetapi tidak ketika hasilnya harus tak terhingga.
Abel
2
@ Bel Itu bukan buggy. Melimpah berarti jumlahnya sangat besar. Terlalu besar untuk diwakili, tetapi masih jauh lebih kecil dari tak terbatas. Menempatkan infinity ke tempat seperti itu mungkin berguna untuk pengendali pengecualian logika aplikasi khusus Anda, tetapi akan salah untuk Python secara umum.
Lutz Prechelt
6
@ Lutz jika muncul sebagai perkalian maka, itu masih perilaku yang tidak konsisten. Besar * besar juga bukan tanpa batas.
Richard Rast
100
Implementasi Python mengikuti standar IEEE-754 dengan cukup baik, yang dapat Anda gunakan sebagai panduan, tetapi ia bergantung pada sistem yang mendasari kompilasi, sehingga perbedaan platform dapat terjadi. Baru-baru ini¹, perbaikan telah diterapkan yang memungkinkan "infinity" serta "inf" , tetapi itu tidak penting di sini.
Bagian berikut ini sama-sama berlaku untuk bahasa apa pun yang menerapkan aritmatika titik apung IEEE dengan benar, tidak khusus hanya untuk Python.
Perbandingan untuk ketimpangan
Ketika berhadapan dengan operator tanpa batas dan operator lebih besar daripada >atau lebih kecil <, berikut ini diperhitungkan:
angka berapa pun termasuk +inflebih tinggi dari-inf
nomor berapa pun termasuk -inflebih rendah dari+inf
-inf tidak lebih tinggi atau lebih rendah dari -inf
setiap perbandingan yang terlibat NaNsalah ( inftidak lebih tinggi, atau lebih rendah dari NaN)
Perbandingan untuk kesetaraan
Jika dibandingkan untuk kesetaraan, +inf dan +infsama, seperti apa adanya -infdan -inf. Ini adalah masalah yang banyak diperdebatkan dan mungkin terdengar kontroversial bagi Anda, tetapi itu dalam standar IEEE dan Python berperilaku seperti itu.
Tentu saja, +inf tidak sama dengan -infdan segala sesuatu, termasuk NaNdirinya sendiri, tidak sama dengan NaN.
Perhitungan dengan tak terhingga
Sebagian besar perhitungan dengan tak terhingga akan menghasilkan tak terhingga, kecuali kedua operan adalah tak terhingga, ketika divisi operasi atau modulo, atau dengan perkalian dengan nol, ada beberapa aturan khusus yang perlu diingat:
ketika dikalikan dengan nol, yang hasilnya tidak ditentukan, hasilnya NaN
ketika membagi angka apa pun (kecuali tak terhingga itu sendiri) dengan tak terhingga, yang menghasilkan 0.0atau -0.0².
ketika membagi (termasuk modulo) infinity positif atau negatif dengan infinity positif atau negatif, hasilnya tidak terdefinisi, jadi NaN.
ketika melakukan inf - inf, hasilnya tidak terdefinisi: NaN;
ketika melakukan inf - -inf, hasilnya adalah inf;
ketika melakukan -inf - inf, hasilnya adalah -inf;
ketika melakukan -inf - -inf, hasilnya tidak terdefinisi: NaN.
saat menambahkan, ini juga bisa mengejutkan:
ketika melakukan inf + inf, hasilnya adalah inf;
ketika melakukan inf + -inf, hasilnya tidak terdefinisi: NaN;
ketika melakukan -inf + inf, hasilnya tidak terdefinisi: NaN;
ketika melakukan -inf + -inf, hasilnya adalah -inf.
menggunakan math.pow, powatau **rumit, karena tidak berperilaku sebagaimana mestinya. Itu melempar pengecualian melimpah ketika hasil dengan dua bilangan real terlalu tinggi untuk muat pelampung presisi ganda (harus mengembalikan tak terhingga), tetapi ketika inputnya infatau -inf, itu berperilaku benar dan mengembalikan salah satu infatau 0.0. Ketika argumen kedua adalah NaN, ia kembali NaN, kecuali argumen pertama adalah 1.0. Ada lebih banyak masalah, tidak semua dibahas dalam dokumen .
math.expmenderita masalah yang sama dengan math.pow. Solusi untuk memperbaiki ini untuk overflow adalah dengan menggunakan kode yang mirip dengan ini:
try:
res = math.exp(420000)exceptOverflowError:
res = float('inf')
Catatan
Catatan 1: sebagai peringatan tambahan, yang seperti yang didefinisikan oleh standar IEEE, jika hasil perhitungan Anda di bawah atau melebihi, hasilnya tidak akan menjadi kesalahan di bawah atau overflow, tetapi tak terhingga positif atau negatif: 1e308 * 10.0hasil inf.
Catatan 2: karena kalkulasi apa pun dengan NaNpengembalian NaNdan perbandingan apa pun dengan NaN, termasuk NaNdirinya sendiri false, Anda harus menggunakan math.isnanfungsi ini untuk menentukan apakah suatu angka memang benar NaN.
Catatan 3: meskipun Python mendukung penulisan float('-NaN'), tanda diabaikan, karena tidak ada tanda pada NaNinternal. Jika Anda membagi -inf / +inf, hasilnya adalah NaNtidak -NaN(tidak ada hal seperti itu).
Catatan 4: berhati-hatilah untuk mengandalkan salah satu di atas, karena Python bergantung pada C atau Java library yang dikompilasi untuk dan tidak semua sistem yang mendasarinya menerapkan semua perilaku ini dengan benar. Jika Anda ingin memastikan, uji untuk tak terbatas sebelum melakukan perhitungan Anda.
¹) Baru-baru ini berarti sejak versi 3.2 .
²) Floating point mendukung nol positif dan negatif, jadi: x / float('inf')pertahankan tanda dan -1 / float('inf')hasil -0.0, 1 / float(-inf)hasil -0.0, 1 / float('inf')hasil 0.0dan -1/ float(-inf)hasil 0.0. Selain itu, 0.0 == -0.0adalahtrue , Anda harus memeriksa secara manual tanda jika Anda tidak ingin menjadi benar.
Nitpick kecil: tidak setiap perhitungan dengan infinity menghasilkan infinity:-1 * float('infinity') == -inf
Evan Krall
4
Itu sebabnya saya mengatakan itu adalah nitpick kecil . Anda membuat saya khawatir sebentar bahwa tanda itu akan benar-benar diabaikan ketika bekerja dengan tak terbatas, dan saya ingin mengklarifikasi untuk orang lain.
Evan Krall
12
Ya, hampir: 1 / float ('infinity') == 0.0
Phil
3
@ Phil: Walaupun saya cukup yakin Anda hanya berusaha menunjukkan bahwa tidak semua perhitungan dengan inf menghasilkan inf atau NaN, saya hanya ingin menjelaskan kepada orang lain yang mungkin membaca komentar, bahwa 1 / float ('infinity ') == 0,0 benar; karena, ketika Anda mendekati ketidakterbatasan, hasil dari divisi mendekati 0. Saya tahu itu hanya kalkulus dasar, tetapi saya ingin memastikan mereka yang membaca mengerti, atau setidaknya memiliki petunjuk mengapa, hasilnya adalah apa adanya.
Anthony Pace
1
Saya merasa bahwa jawaban ini jauh lebih baik daripada jawaban yang diterima.
Representasi floating point IEEE 754 yang digunakan oleh semua prosesor modern memiliki beberapa pola bit khusus yang dicadangkan untuk infinity positif (tanda = 0, exp = ~ 0, frac = 0), infinity negatif (tanda = 1, exp = ~ 0, frac = 0 ), dan banyak NaN (Bukan Angka: exp = ~ 0, frac ≠ 0).
Yang perlu Anda khawatirkan: beberapa aritmatika dapat menyebabkan pengecualian / perangkap titik mengambang, tetapi itu tidak terbatas hanya pada konstanta "menarik" ini.
Jadi jika aritmatika saya terlalu besar, itu mungkin menjadi inf?
Casebash
@Casebash Tidak, itu akan menyebabkan OverflowError.
wizzwizz4
2
Saya menemukan peringatan yang sejauh ini tidak ada yang disebutkan. Saya tidak tahu apakah itu akan sering muncul dalam situasi praktis, tetapi ini demi kelengkapan.
Biasanya, menghitung angka tak terbatas modulo mengembalikan dirinya sebagai pelampung, tetapi sebagian kecil tak terbatas modulo kembali nan(bukan angka). Berikut ini sebuah contoh:
>>>from fractions importFraction>>>from math import inf
>>>3% inf
3.0>>>3.5% inf
3.5>>>Fraction('1/3')% inf
nan
1e309
akan ditafsirkan sebagai+inf
dan-1e309
akan ditafsirkan sebagai-inf
.Jawaban:
Anda masih bisa mendapatkan nilai bukan angka (NaN) dari aritmatika sederhana yang melibatkan
inf
:Perhatikan bahwa Anda biasanya tidak akan mendapatkan
inf
nilai melalui perhitungan aritmatika biasa:The
inf
nilai dianggap sebagai nilai yang sangat khusus dengan semantik yang tidak biasa, jadi lebih baik untuk mengetahui tentangOverflowError
langsung melalui pengecualian, daripada memilikiinf
nilai diam-diam disuntikkan ke dalam perhitungan Anda.sumber
**
tampak agak buggy. Ketika meluap dengan angka nyata, ia melempar kesalahan, tetapi ketika salah satu operandnya adalahinf
atau-inf
, ia mengembalikan salah satu0.0
atauinf
. Jadi tidak bekerja dengan benar ketika input inifinty, tetapi tidak ketika hasilnya harus tak terhingga.Implementasi Python mengikuti standar IEEE-754 dengan cukup baik, yang dapat Anda gunakan sebagai panduan, tetapi ia bergantung pada sistem yang mendasari kompilasi, sehingga perbedaan platform dapat terjadi. Baru-baru ini¹, perbaikan telah diterapkan yang memungkinkan "infinity" serta "inf" , tetapi itu tidak penting di sini.
Bagian berikut ini sama-sama berlaku untuk bahasa apa pun yang menerapkan aritmatika titik apung IEEE dengan benar, tidak khusus hanya untuk Python.
Perbandingan untuk ketimpangan
Ketika berhadapan dengan operator tanpa batas dan operator lebih besar daripada
>
atau lebih kecil<
, berikut ini diperhitungkan:+inf
lebih tinggi dari-inf
-inf
lebih rendah dari+inf
+inf
yang tidak lebih tinggi atau lebih rendah dari+inf
-inf
tidak lebih tinggi atau lebih rendah dari-inf
NaN
salah (inf
tidak lebih tinggi, atau lebih rendah dariNaN
)Perbandingan untuk kesetaraan
Jika dibandingkan untuk kesetaraan,
+inf
dan+inf
sama, seperti apa adanya-inf
dan-inf
. Ini adalah masalah yang banyak diperdebatkan dan mungkin terdengar kontroversial bagi Anda, tetapi itu dalam standar IEEE dan Python berperilaku seperti itu.Tentu saja,
+inf
tidak sama dengan-inf
dan segala sesuatu, termasukNaN
dirinya sendiri, tidak sama denganNaN
.Perhitungan dengan tak terhingga
Sebagian besar perhitungan dengan tak terhingga akan menghasilkan tak terhingga, kecuali kedua operan adalah tak terhingga, ketika divisi operasi atau modulo, atau dengan perkalian dengan nol, ada beberapa aturan khusus yang perlu diingat:
NaN
0.0
atau-0.0
².NaN
.inf - inf
, hasilnya tidak terdefinisi:NaN
;inf - -inf
, hasilnya adalahinf
;-inf - inf
, hasilnya adalah-inf
;-inf - -inf
, hasilnya tidak terdefinisi:NaN
.inf + inf
, hasilnya adalahinf
;inf + -inf
, hasilnya tidak terdefinisi:NaN
;-inf + inf
, hasilnya tidak terdefinisi:NaN
;-inf + -inf
, hasilnya adalah-inf
.math.pow
,pow
atau**
rumit, karena tidak berperilaku sebagaimana mestinya. Itu melempar pengecualian melimpah ketika hasil dengan dua bilangan real terlalu tinggi untuk muat pelampung presisi ganda (harus mengembalikan tak terhingga), tetapi ketika inputnyainf
atau-inf
, itu berperilaku benar dan mengembalikan salah satuinf
atau0.0
. Ketika argumen kedua adalahNaN
, ia kembaliNaN
, kecuali argumen pertama adalah1.0
. Ada lebih banyak masalah, tidak semua dibahas dalam dokumen .math.exp
menderita masalah yang sama denganmath.pow
. Solusi untuk memperbaiki ini untuk overflow adalah dengan menggunakan kode yang mirip dengan ini:Catatan
Catatan 1: sebagai peringatan tambahan, yang seperti yang didefinisikan oleh standar IEEE, jika hasil perhitungan Anda di bawah atau melebihi, hasilnya tidak akan menjadi kesalahan di bawah atau overflow, tetapi tak terhingga positif atau negatif:
1e308 * 10.0
hasilinf
.Catatan 2: karena kalkulasi apa pun dengan
NaN
pengembalianNaN
dan perbandingan apa pun denganNaN
, termasukNaN
dirinya sendirifalse
, Anda harus menggunakanmath.isnan
fungsi ini untuk menentukan apakah suatu angka memang benarNaN
.Catatan 3: meskipun Python mendukung penulisan
float('-NaN')
, tanda diabaikan, karena tidak ada tanda padaNaN
internal. Jika Anda membagi-inf / +inf
, hasilnya adalahNaN
tidak-NaN
(tidak ada hal seperti itu).Catatan 4: berhati-hatilah untuk mengandalkan salah satu di atas, karena Python bergantung pada C atau Java library yang dikompilasi untuk dan tidak semua sistem yang mendasarinya menerapkan semua perilaku ini dengan benar. Jika Anda ingin memastikan, uji untuk tak terbatas sebelum melakukan perhitungan Anda.
¹) Baru-baru ini berarti sejak versi 3.2 .
²) Floating point mendukung nol positif dan negatif, jadi:
x / float('inf')
pertahankan tanda dan-1 / float('inf')
hasil-0.0
,1 / float(-inf)
hasil-0.0
,1 / float('inf')
hasil0.0
dan-1/ float(-inf)
hasil0.0
. Selain itu,0.0 == -0.0
adalahtrue
, Anda harus memeriksa secara manual tanda jika Anda tidak ingin menjadi benar.sumber
-1 * float('infinity') == -inf
Begitu juga C99 .
Representasi floating point IEEE 754 yang digunakan oleh semua prosesor modern memiliki beberapa pola bit khusus yang dicadangkan untuk infinity positif (tanda = 0, exp = ~ 0, frac = 0), infinity negatif (tanda = 1, exp = ~ 0, frac = 0 ), dan banyak NaN (Bukan Angka: exp = ~ 0, frac ≠ 0).
Yang perlu Anda khawatirkan: beberapa aritmatika dapat menyebabkan pengecualian / perangkap titik mengambang, tetapi itu tidak terbatas hanya pada konstanta "menarik" ini.
sumber
OverflowError
.Saya menemukan peringatan yang sejauh ini tidak ada yang disebutkan. Saya tidak tahu apakah itu akan sering muncul dalam situasi praktis, tetapi ini demi kelengkapan.
Biasanya, menghitung angka tak terbatas modulo mengembalikan dirinya sebagai pelampung, tetapi sebagian kecil tak terbatas modulo kembali
nan
(bukan angka). Berikut ini sebuah contoh:Saya mengajukan masalah pada pelacak bug Python. Itu dapat dilihat di https://bugs.python.org/issue32968 .
Pembaruan: ini akan diperbaiki dalam Python 3.8 .
sumber
dalam
1/x
sepersekian, sampai saatx = 1e-323
ituinf
tetapi ketikax = 1e-324
atau sedikit itu melemparZeroDivisionError
jadi berhati-hatilah!
sumber