隨手扎
表示無限大。運算與比較(Python)
前言
在做LeetCode題目。然後因為我思考邏輯的關係,會需要使用到無限大(Inf
)的概念,所以首先自幹的一個:
class Inf(numbers.Number):
def __gt__(self, n: numbers.Number):
return True
def __eq__(self, n: numbers.Number):
if isinstance(n, Inf): return True
else: return False
遺憾的是,這雖然可以處理Inf() > int(1)
,卻無法處理int(1) > Inf()
的問題。無法輕易直接修改內置類型int
,要是在多包一層感覺有些彆扭。所以找找看Python有沒有像EMCAScript內有Infinity
的東西。可是…我第一個看的卻是日文內容。
Google中文第一個查到的也是簡體中文。要不就是Numpy
的東西。
於是乎,這篇簡單的分享就出來了。
※ 最開始,我還有在numbers裡面找,無果。
無限大的表示
inf = float('Inf')
inf # => inf
type(inf) # => float
要產生 無限大 (Inf
)概念的物件實體(object instance),在Python需要使用float()
,同時他也會是float
類別。
※ 在Python3,整數類別(int
),會自動轉換成大整數(bigNumber
)。從這個角度來看,無限大不是整數,也不是numbers.Number似乎就合理地設計多。
float('-inf') # => -inf
-float('inf') # => -inf
float('Infinity') # => inf
float('-Infinity') # => -inf
當然也有負無限大(negative infinity)。而且"inf"
和""Infinity"
是不區分大小寫的。
float("INF")
float("inF")
float("iNF")
float("INFINITY")
float("infinity")
float("inFiNiTY")
不過他沒法像EMCASCript,透過實數除零來獲得,會報錯。(可能基於多數程式設計,不會預期使用到無限大)
// Welcome to Node.js v12.13.0.
// Type ".help" for more information.
1/0 // => Infinity
# python3
1.0/0.0
'''
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: float division by zero
'''
系統浮點數最大值
儘管無法從除零得到,但可以從系統允許的最大浮點數值得到。
import sys
sys.float_info.max # depend your machine and python implement. => 1.7976931348623157e+308
f_inf_num = sys.float_info.max * 2
f_inf_num # => inf
f_inf_num = sys.float_info.max + sys.float_info.max
f_inf_num # => inf
不過浮點數(float)會有精度遺失的問題,運算數值過小會看不出差異。
f_inf_num = sys.float_info.max
(f_inf_num + 1) == sys.float_info.max # => True
f_inf_num + 1 # => 1.7976931348623157e+308 (same as `sys.float_info.max`)
更多關於無限大
關於float()
的描述:
sign ::= "+" | "-"
infinity ::= "Infinity" | "inf"
nan ::= "nan"
numeric_value ::= floatnumber | infinity | nan
numeric_string ::= [sign] numeric_value
- 你可以明確的加上正負號
"Infinity"
和"inf"
瑪ㄟ通- 是的還有
nan
(Not A Number)
float("+inf")
float("+infinity")
float("nan")
float("+nan")
float("-nan")
float("Nan")
float("NaN")
float("NAN")
math package
Python 3.5以後,在math
定義了inf
和nan
,相當於float('inf')
和float('nan')
import math
math.inf # => inf
math.inf == float('inf') # => True
########
math.nan # => nan
math.nan == float('nan') # => False. nan can't compare
str(math.nan) == str(float('nan')) # => True. Need convert to other type first.
關於更多math(more about math)
https://docs.python.org/3.8/library/math.html?highlight=math#constants
math.pi # => 3.141592...
math.e # => 2.718281...
math.tau # => 6.283185... (after Python 3.6)
math.inf # => inf (after Python 3.5)
math.nan # => nan (after Python 3.5)
math.isinf(float('inf')) # => True
比較
Inf
大部分合乎預期。
inf = float('inf')
inf > 99999999999 # => True
inf > 99999999999.9999999999 # => True
99999999999 > inf # => False
99999999999.9999999999 > inf # => False
解決了<int>
無法和<Inf>
比較的問題。此外,和numpy.inf
無異。
import numpy as np
float('inf') == np.inf # => True
運算
##### ADD #######
float('inf') + 100 # => inf
float('inf') + float('inf') # => inf
##### SUB #######
float('inf') - 100 # => inf
float('inf') - float('inf') # => nan
##### MUL #######
float('inf') * 2 # => inf
float('inf') * float('inf') # => inf
float('inf') * 0 # => nan
##### DIV #######
float('inf') / 2 # => inf
float('inf') / float('inf') # => nan
0 / float('inf') # => 0.0
幾個可能比較需要注意的,可能和你想的不同:
- 最好不要
inf - inf
雖然inf==inf
為真,但inf
無法直接比較。會得到nan
。 - 最好不要
inf / inf
雖然inf==inf
為真,但不會得到1
,會得到nan
。 - 最好不要
inf * 0
會得到nan
。 - 最好不要
inf / 0
雖然數學上可以表示為inf
,但這裡不可以除零,會報錯。
補充
Thank dale and papna answer my question at Freenode IRC.
IEEE 754相關標準這樣定義:
- n / 0 => Inf
- 0 * Inf => Nan
起初,我認為0
乘上任何數字還是0
;但是Inf
乘上任何數字也幾乎有為Inf
的特性。
如果這樣想:
# x limit to Infinity
a = 1/x
b = x
# a * b = ?
由於Inf
其實不是任何數字,所以兩個x
無法互消變成1
。也就是這個結果 有不確定性 。對Inf
不是任何數字,不是cardinal number,所以在很多時候行為不與數字相同。是的…這還和離散數學有關了。
轉換
inf
沒法轉成整數。
# int(float('inf'))
'''
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OverflowError: cannot convert float infinity to integer
'''
但可以轉成字串。
str(float('inf')) # => 'inf'