Python มีค่าเป็นบวกและลบ:
float("inf"), float("-inf")
นี่ดูเหมือนจะเป็นคุณลักษณะประเภทที่ต้องมีข้อแม้บางอย่าง มีอะไรบ้างที่ฉันควรระวัง?
Python มีค่าเป็นบวกและลบ:
float("inf"), float("-inf")
นี่ดูเหมือนจะเป็นคุณลักษณะประเภทที่ต้องมีข้อแม้บางอย่าง มีอะไรบ้างที่ฉันควรระวัง?
คำตอบ:
คุณยังสามารถรับค่าที่ไม่เป็นตัวเลข (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ก็เช่นกัน 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 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