Rational numbers是分子和分母都是整數的分數。
例如,我們可以把2//3儲存成精確的分數,而不是Float64的近似值0.6666...。
好處是(除了整數溢位這種極端情況之外),有理數會保持精確,避免浮點數經常難以避免的捨入誤差。
有理數是很單純的數值型別,運作方式也大致符合你的預期。 由於有理數從早期版本開始就是 Julia 的標準型別,大多數函式都會像接受整數和浮點數那樣,接受它作為輸入。
建立的方法很簡單,只要在兩個整數之間使用//就行了。
julia> 3//4
3//4
julia> a = 3; b = 4;
julia> a//b
3//4
公因數會自動約掉,把分數化成「最簡形式」:也就是能精確表示該分數的最小整數,而且分母為非負數。
julia> 5//15
1//3
julia> 5//-15
-1//3
常見的arithmetic operators + - * / ^ %可以用在有理數上,基本上和其他數值型別一樣。
整數和其他Rational也能參與運算,並得到Rational的結果。
運算式中若包含float,結果就會是float,因此可能會有精度損失。
如果想要float,只要用float()函式把有理數轉換過去就行了。
在冗長的計算中先用有理數保持精度,最後再轉成浮點數,這是很常見的做法。
julia> 3//4 + 1//3 # addition
13//12
julia> 3//4 * 1//3 # multiplication
1//4
julia> 3//4 / 1//3 # division
9//4
julia> 3//4 ^ 2 # exponentiation
3//16
julia> 3//4 + 5 # rational and int => rational
23//4
julia> 3//4 + 5.3 # rational and float => float
6.05
julia> float(3//4) # casting
0.75
在 Julia 中,有理數就只是數字。 編譯器通常會視需要自動轉換型別。
不過要注意,比較運算只適用於具有有限小數表示法的分數:
julia> 3//4 == 0.75
true
julia> 3//4 < 0.74
false
否則的話,Rational應該先轉型成Float再進行比較:
julia> 1//3 == 1/3
false
julia> float(1//3) == 1/3
true
數學函式可以接受有理數作為輸入,但結果可能是浮點數:
julia> sqrt(9//16)
0.75
某個研究機構注意到,旗下有些初階研究人員在分析時採用了不盡理想的方法。 其中一個做法,就是在做後續計算之前,直接把離散機率轉換成浮點數(也就是實數)。
資深研究人員偏好使用有理數來計算,因為這樣可能得到更高的精確度;他們也想確認初階研究人員的不良做法是否影響了研究結果。
這些研究分成兩種類型:
資深研究人員請你撰寫一些函式,幫助他們判斷使用浮點數所做的分析是否出現捨入誤差;如果確實有誤差,也請你提供結果的精確有理數。
rationalize(successes, trials)函式接收兩個陣列,successes和trials。
對索引i來說,successes[i]對應的是在trials[i]次試驗中成功的次數。
這個函式會回傳一個有理數陣列,代表成功次數除以試驗次數,順序與輸入陣列相同。
julia> rationalize([1, 2, 3], [4, 5, 6])
3-element Vector{Rational{Int64}}:
1//4
2//5
1//2
同樣地,probabilities(successes, trials)函式接收兩個陣列,successes和trials。
它會回傳一個浮點數陣列,代表成功次數除以試驗次數,順序與輸入陣列相同。
julia> probabilities([1, 2, 3], [4, 5, 6])
3-element Vector{Float64}:
0.25
0.4
0.5
checkmean(successes, trials)接收兩個陣列,successes和trials。
它會比較實際機率的平均值與有理數機率的平均值。
checkmean會回傳true。checkmean會回傳有理數機率。julia> successes, trials = [9, 4, 7, 8, 6], [22, 22, 11, 17, 12];
julia> checkmean(successes, trials)
true
julia> successes, trials = [6, 5, 9, 8, 9], [21, 19, 13, 25, 22];
julia> checkmean(successes, trials)
1873629//4754750
checkprob(successes, trials)接收兩個陣列,successes和trials。
它會比較浮點數機率的總機率與有理數機率的總機率。
checkprob會回傳true。checkprob會回傳有理數機率。julia> successes, trials = [2, 9, 4, 4, 5], [15, 11, 17, 19, 15];
julia> checkprob(successes, trials)
true
julia> successes, trials = [9, 8, 5, 4, 3], [22, 14, 19, 25, 18];
julia> checkprob(sucesses, trials)
12//7315