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 ไม่สูงหรือต่ำกว่า -infNaNเป็นเท็จ ( infไม่สูงกว่าหรือต่ำกว่าNaN)เมื่อเปรียบเทียบความเสมอภาค+infและ+infเท่าเทียมกันเช่นเดียวกับและ-inf -infนี่เป็นปัญหาที่ถกเถียงกันมากและอาจฟังดูขัดแย้งกับคุณ แต่มันอยู่ในมาตรฐาน IEEE และ Python ทำงานแบบนั้น
แน่นอน+infคือไม่เท่ากันไป-infและทุกอย่างรวมถึงตัวเองเป็นไม่เท่ากันไปNaNNaN
การคำนวณส่วนใหญ่ที่มีอนันต์จะให้ผลอนันต์ยกเว้นว่าตัวถูกดำเนินการทั้งสองนั้นเป็นอนันต์เมื่อการหารการดำเนินงานหรือโมดูโลหรือการคูณด้วยศูนย์มีกฎพิเศษบางอย่างที่ต้องจำไว้:
NaN0.0หรือ-0.0²NaNบวกหรือเชิงลบโดยอินฟินิตี้อินฟินิตี้บวกหรือลบผลที่ได้คือไม่ได้กำหนดดังนั้นinf - infผลลัพธ์จะไม่ได้กำหนด:NaN ;inf - -infผลที่ได้คือinf ;-inf - infผลที่ได้คือ-inf ;-inf - -infNaNinf + infผลที่ได้คือinf ;inf + -infผลลัพธ์จะไม่ได้กำหนด:NaN ;-inf + infผลลัพธ์จะไม่ได้กำหนด:NaN ;-inf + -inf-infmath.pow, powหรือ**เป็นเรื่องยุ่งยากตามที่มันไม่ประพฤติตามที่ควร มันพ่นยกเว้นล้นเมื่อผลที่มีสองตัวเลขจริงสูงเกินไปเพื่อให้พอดีกับลอยแม่นยำสอง (มันควรจะกลับอินฟินิตี้) แต่เมื่อเข้าเป็นinfหรือ-infมันจะทำงานได้อย่างถูกต้องและผลตอบแทนอย่างใดอย่างหนึ่งหรือinf 0.0เมื่ออาร์กิวเมนต์ที่สองคือNaNมันกลับเว้นแต่อาร์กิวเมนต์แรกคือNaN 1.0มีปัญหามากขึ้นไม่ทั้งหมดที่มีการกล่าวถึงในเอกสารmath.expmath.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