Menetapkan variabel NaN di python tanpa numpy

103

Sebagian besar bahasa memiliki konstanta NaN yang dapat Anda gunakan untuk menetapkan nilai NaN pada variabel. Bisakah python melakukan ini tanpa menggunakan numpy?

zelinka
sumber
1
C, C ++, java, C #, ocaml, ini adalah bagian dari banyak bahasa.
zelinka
2
NaN, dalam C, adalah NAN; itu adalah konstanta yang ditentukan dalam math.h, pada C99. (Saya merasa adil untuk menyebut versi bahasa standar terbaru sebagai bahasa itu. Jadi "C" adalah C11.) (Lihat stackoverflow.com/questions/1923837/how-to-use-nan-and-inf-in -c ); di C ++, itu NANjuga, ada juga nan(), nanf(), dan nanl(), meskipun aku agak kurang yakin untuk apa yang mereka lakukan. double.NaNdi Jawa, Double.NaNdi C #…
Thanatos

Jawaban:

169

Ya - gunakan math.nan.

>>> from math import nan
>>> print(nan)
nan
>>> print(nan + 2)
nan
>>> nan == nan
False
>>> import math
>>> math.isnan(nan)
True

Sebelum Python 3.5, seseorang dapat menggunakan float("nan")(case insensitive).

Perhatikan bahwa memeriksa untuk melihat apakah dua hal yang NaN sama satu sama lain akan selalu menghasilkan nilai salah. Ini sebagian karena dua hal yang "bukan angka" tidak dapat (secara tegas) dikatakan sama satu sama lain - lihat Apa alasan untuk semua perbandingan yang mengembalikan nilai false untuk IEEE754 NaN? untuk detail dan informasi lebih lanjut.

Sebaliknya, gunakan math.isnan(...)jika Anda perlu menentukan apakah suatu nilai adalah NaN atau tidak.

Selain itu, semantik ==operasi yang tepat pada nilai NaN dapat menyebabkan masalah halus saat mencoba menyimpan NaN di dalam jenis penampung seperti listatau dict(atau saat menggunakan jenis penampung khusus). Lihat Memeriksa keberadaan NaN di wadah untuk lebih jelasnya.


Anda juga dapat membuat angka NaN menggunakan modul desimal Python :

>>> from decimal import Decimal
>>> b = Decimal('nan')
>>> print(b)
NaN
>>> print(repr(b))
Decimal('NaN')
>>>
>>> Decimal(float('nan'))
Decimal('NaN')
>>> 
>>> import math
>>> math.isnan(b)
True

math.isnan(...) juga akan bekerja dengan objek Desimal.


Namun, Anda tidak dapat membuat bilangan NaN dalam modul pecahan Python :

>>> from fractions import Fraction
>>> Fraction('nan')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python35\lib\fractions.py", line 146, in __new__
    numerator)
ValueError: Invalid literal for Fraction: 'nan'
>>>
>>> Fraction(float('nan'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python35\lib\fractions.py", line 130, in __new__
    value = Fraction.from_float(numerator)
  File "C:\Python35\lib\fractions.py", line 214, in from_float
    raise ValueError("Cannot convert %r to %s." % (f, cls.__name__))
ValueError: Cannot convert nan to Fraction.

Kebetulan, Anda juga dapat melakukan float('Inf'), Decimal('Inf')atau math.inf(3.5 +) untuk menetapkan jumlah tak terbatas. (Dan juga lihat math.isinf(...))

Namun melakukan Fraction('Inf')atau Fraction(float('inf'))tidak diizinkan dan akan mengeluarkan pengecualian, seperti NaN.

Jika Anda ingin cara yang cepat dan mudah untuk memeriksa apakah suatu nomor bukan NaN atau tidak terbatas, Anda dapat menggunakan math.isfinite(...)mulai Python 3.2+.


Jika Anda ingin melakukan pemeriksaan serupa dengan bilangan kompleks, cmathmodul berisi sekumpulan fungsi dan konstanta yang serupa dengan mathmodul:

Michael0x2a
sumber
2
Perhatikan bahwa menggunakan float ('nan) adalah 3x lebih lambat daripada menggunakan np.nan, dan sekitar 6,5 kali lebih lambat daripada menetapkan nan = float (' nan ') sekali dan kemudian menggunakan variabel' nan 'untuk semua tugas berikut (seperti yang disarankan dalam abarnert's menjawab).
Daniel Goldfarb
18
nan = float('nan')

Dan sekarang Anda memiliki konstanta nan,.

Anda juga dapat membuat nilai NaN untuk desimal. Desimal .:

dnan = Decimal('nan')
abarnert
sumber
Ini adalah jawaban paling efisien untuk beberapa tugas nan: Yaitu, gunakan float ('nan') hanya sekali, lalu gunakan konstanta yang ditetapkan untuk semua tugas yang tersisa. Namun jika Anda hanya mengerjakan satu atau dua tugas dengan total nan, maka menggunakan numpy.nan adalah yang tercepat.
Daniel Goldfarb
7

Penggunaan float("nan"):

>>> float("nan")
nan
orlp
sumber
6

Anda bisa melakukannya float('nan')untuk mendapatkan NaN.

BrenBarn
sumber
6

Anda bisa mendapatkan NaN dari "inf - inf", dan Anda bisa mendapatkan "inf" dari angka yang lebih besar dari 2e308, jadi, saya biasanya menggunakan:

>>> inf = 9e999
>>> inf
inf
>>> inf - inf
nan
Junior Polegato
sumber
3
Jawaban ini ditolak dengan tidak masuk akal. Saya menulis banyak tes penguraian kecil dalam file .txt dan menggunakan ast.literal_eval untuk mendapatkan bagian keluaran yang diharapkan. Tidak mungkin untuk memanggil float ('nan') di sana, dan jawaban ini sangat membantu saya.
Vitalik Verhovodov
0

Cara yang lebih konsisten (dan kurang buram) untuk menghasilkan inf dan -inf adalah dengan menggunakan float () lagi:

>> positive_inf = float('inf')
>> positive_inf
inf
>> negative_inf = float('-inf')
>> negative_inf
-inf

Perhatikan bahwa ukuran pelampung bervariasi tergantung pada arsitekturnya, jadi sebaiknya hindari penggunaan angka ajaib seperti 9e999, bahkan jika itu mungkin berhasil.

import sys
sys.float_info
sys.float_info(max=1.7976931348623157e+308,
               max_exp=1024, max_10_exp=308,
               min=2.2250738585072014e-308, min_exp=-1021,
               min_10_exp=-307, dig=15, mant_dig=53,
               epsilon=2.220446049250313e-16, radix=2, rounds=1)
pengguna3685621
sumber