การกำหนดตัวแปร NaN ใน python โดยไม่มี numpy


103

ภาษาส่วนใหญ่มีค่าคงที่ NaN ที่คุณสามารถใช้เพื่อกำหนดตัวแปรเป็นค่า NaN python สามารถทำได้โดยไม่ต้องใช้ numpy หรือไม่?


1
C, C ++, java, C #, ocaml เป็นส่วนหนึ่งของภาษามากมาย
zelinka

2
NaN ใน C คือNAN; มันเป็นค่าคงที่ที่กำหนดไว้ในmath.hC99 (ฉันรู้สึกว่ามันยุติธรรมที่จะเรียกภาษาเวอร์ชันมาตรฐานล่าสุดว่าภาษานั้นดังนั้น "C" คือ C11) (ดูstackoverflow.com/questions/1923837/how-to-use-nan-and-inf-in -c ); ใน C ++ มันNANเป็นอย่างดีนอกจากนี้ยังมีnan(), nanf()และnanl()แม้ว่าฉันบิตบางน้อยเป็นสิ่งที่พวกเขาทำ double.NaNใน Java Double.NaNใน C # …
Thanatos

คำตอบ:


169

ใช่ - math.nanการใช้งาน

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

ก่อน Python 3.5 สามารถใช้ได้float("nan")(ไม่คำนึงถึงตัวพิมพ์เล็กและใหญ่)

โปรดทราบว่าการตรวจสอบเพื่อดูว่าสองสิ่งที่เป็น NaN เท่ากันหรือไม่จะส่งกลับเท็จเสมอ ส่วนหนึ่งเป็นเพราะสองสิ่งที่ "ไม่ใช่ตัวเลข" ไม่สามารถพูดได้ (พูดอย่างเคร่งครัด) ว่าเท่าเทียมกัน - ดูเหตุผลสำหรับการเปรียบเทียบทั้งหมดที่คืนค่าเป็นเท็จสำหรับค่า IEEE754 NaN คืออะไร? สำหรับรายละเอียดและข้อมูลเพิ่มเติม

ให้ใช้math.isnan(...)หากคุณต้องการพิจารณาว่าค่าเป็น NaN หรือไม่

นอกจากนี้ความหมายที่แน่นอนของการ==ดำเนินการกับค่า NaN อาจทำให้เกิดปัญหาเล็กน้อยเมื่อพยายามจัดเก็บ NaN ไว้ในประเภทคอนเทนเนอร์เช่นlistหรือdict(หรือเมื่อใช้ประเภทคอนเทนเนอร์ที่กำหนดเอง) ดูการตรวจสอบสถานะ NaN ในคอนเทนเนอร์สำหรับรายละเอียดเพิ่มเติม


คุณยังสามารถสร้างตัวเลข NaN โดยใช้โมดูลทศนิยมของ 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(...) จะทำงานกับวัตถุทศนิยม


อย่างไรก็ตามคุณไม่สามารถสร้างตัวเลข NaN ในโมดูลเศษส่วนของ 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.

อนึ่งนอกจากนี้คุณยังสามารถทำfloat('Inf'), Decimal('Inf')หรือmath.inf(3.5 ขึ้นไป) เพื่อกำหนดหมายเลขอนันต์ (และดูด้วยmath.isinf(...))

อย่างไรก็ตามการทำFraction('Inf')หรือFraction(float('inf'))ไม่ได้รับอนุญาตและจะทำให้เกิดข้อยกเว้นเช่นเดียวกับ NaN

หากคุณต้องการวิธีที่ง่ายและรวดเร็วในการตรวจสอบว่าตัวเลขนั้นไม่ใช่ทั้ง NaN หรือไม่มีที่สิ้นสุดคุณสามารถใช้math.isfinite(...)เป็น Python 3.2+ ได้


หากคุณต้องการทำการตรวจสอบที่คล้ายกันกับจำนวนเชิงซ้อนcmathโมดูลจะมีชุดฟังก์ชันและค่าคงที่ที่คล้ายกันเป็นmathโมดูล:


2
โปรดทราบว่าการใช้ float ('nan) จะช้ากว่าการใช้ np.nan 3 เท่าและช้ากว่าการกำหนด nan = float (' nan ') ประมาณ 6.5 เท่าหนึ่งครั้งจากนั้นใช้ตัวแปร' nan 'สำหรับการกำหนดทั้งหมดต่อไปนี้ (ตามที่แนะนำใน abarnert's ตอบ).
Daniel Goldfarb

18
nan = float('nan')

และตอนนี้คุณมีค่าคงที่nanแล้ว

คุณสามารถสร้างค่า NaN สำหรับทศนิยมได้ในทำนองเดียวกันทศนิยม:

dnan = Decimal('nan')

นี่เป็นคำตอบที่มีประสิทธิภาพที่สุดสำหรับการกำหนดนาโนหลายครั้งนั่นคือใช้ float ('nan') เพียงครั้งเดียวจากนั้นใช้ค่าคงที่ที่กำหนดสำหรับการกำหนดที่เหลือทั้งหมด อย่างไรก็ตามหากคุณทำการกำหนด nan total เพียงหนึ่งหรือสองงานการใช้ numpy.nan นั้นเร็วที่สุด
Daniel Goldfarb



6

คุณสามารถรับ NaN จาก "inf - inf" และคุณจะได้รับ "inf" จากตัวเลขที่มากกว่า 2e308 ดังนั้นโดยทั่วไปฉันจะใช้:

>>> inf = 9e999
>>> inf
inf
>>> inf - inf
nan

3
คำตอบนี้ลดลงอย่างไม่มีเหตุผล ฉันกำลังเขียนการทดสอบการแยกวิเคราะห์ขนาดเล็กจำนวนมากในไฟล์. txt และใช้ ast.literal_eval เพื่อรับส่วนผลลัพธ์ที่คาดหวัง เป็นไปไม่ได้ที่จะเรียก float ('nan') ที่นั่นและคำตอบนี้มีประโยชน์สำหรับฉัน
Vitalik Verhovodov

0

วิธีที่สอดคล้องกันมากขึ้น (และทึบแสงน้อยกว่า) ในการสร้าง inf และ -inf คือการใช้ float () อีกครั้ง:

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

โปรดทราบว่าขนาดของลูกลอยจะแตกต่างกันไปขึ้นอยู่กับสถาปัตยกรรมดังนั้นจึงควรหลีกเลี่ยงการใช้ตัวเลขวิเศษเช่น 9e999 แม้ว่าจะได้ผลก็ตาม

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)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.