fractions 模組讓我們可以建立並操作rational numbers:也就是分子為整數、分母也為整數的分數。
例如,我們可以把 2/3 存成精確的分數,而不是近似的float值0.6666...。
和 int、float、complex 這些數字不同,分數沒有字面值的寫法。
不過,分數建構子的彈性相當大。
最明顯的是,它可以接受兩個整數。 公因數會自動約掉,把分數化成「最簡形式」(能精確表示這個分數的最小整數):
>>> from fractions import Fraction
>>> f1 = Fraction(2, 3) # 2/3
>>> f1
Fraction(2, 3)
>>> f2 = Fraction(6, 9)
>>> f2
Fraction(2, 3) # automatically simplified
>>> f1 == f2
True
分數建構子也可以解析字串表示法:
>>> f3 = Fraction('2/3')
>>> f3
Fraction(2, 3)
它也可以搭配 float 參數運作,但這可能會碰上問題,因為小數值在內部是以二進位近似表示的。
關於這個表示法問題的更多說明,請參閱 0.30000000000000004 網站,以及 Python 文件中的 浮點數運算:問題與限制 。
若想在分數中使用浮點數時獲得更可靠的結果,可以使用<fraction>.limit_denominator()方法。
.limit_denominator()可以接受一個整數參數,如果你有特定需求的話;不過即使是預設值(max_denominator=1000000)也能運作良好,給出可接受又簡單的近似值。
>>> Fraction(1.2)
Fraction(5404319552844595, 4503599627370496)
>>> Fraction(1.2).limit_denominator()
Fraction(6, 5)
和其他數值型別一樣,常見的arithmetic operators+ - * / **也能用在分數上。
整數和其他 Fraction 可以一起參與運算,結果仍是 Fraction。
運算式裡只要包含 float,輸出就會是 float,因此可能造成精度損失。
>>> Fraction(2, 3) + Fraction(1, 4) # addition
Fraction(11, 12)
>>> Fraction(2, 3) * Fraction(6, 5) # multiply fractions
Fraction(4, 5)
>>> Fraction(2, 3) * 6 / 5 # fraction with integers
Fraction(4, 5)
>>> Fraction(2, 3) * 1.2 # fraction with float -> float
0.7999999999999999
>>> Fraction(2, 3) ** 2 # exponentiation with integer
Fraction(4, 9)
分數很適合在計算過程中保留精度,但可能不是你想要的最終輸出。
可以個別取得分子和分母,或是以元組的形式取得(tuples會在之後的概念中討論):
>>> Fraction(2, 3).numerator
2
>>> Fraction(2, 3).denominator
3
>>> Fraction(2, 3).as_integer_ratio()
(2, 3)
各種標準的 Python 數值函式,也會給出和處理int、float型別時相同的結果:
>>> round(Fraction(11, 3))
4
>>> from math import floor, ceil
>>> floor(Fraction(11, 3))
3
>>> ceil(Fraction(11, 3))
4
>>> float(Fraction(11, 3))
3.6666666666666665