學習軌道
/
Julia
Julia
/
練習
/
問題重重的機率
問題重重的機率

問題重重的機率

學習練習

簡介

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

說明

某個研究機構注意到,旗下有些初階研究人員在分析時採用了不盡理想的方法。 其中一個做法,就是在做後續計算之前,直接把離散機率轉換成浮點數(也就是實數)。

資深研究人員偏好使用有理數來計算,因為這樣可能得到更高的精確度;他們也想確認初階研究人員的不良做法是否影響了研究結果。

這些研究分成兩種類型:

  • 執行了多次測試,每次都會得到一個離散的成功機率,接著再計算這些機率的平均值。
  • 測試了許多獨立事件,並將它們相乘,藉此算出所有事件同時發生的總機率。

資深研究人員請你撰寫一些函式,幫助他們判斷使用浮點數所做的分析是否出現捨入誤差;如果確實有誤差,也請你提供結果的精確有理數。

1. 提供成功次數與試驗次數的比值

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

2. 求出成功次數與試驗次數對應的實際機率

同樣地,probabilities(successes, trials)函式接收兩個陣列,successes和trials。 它會回傳一個浮點數陣列,代表成功次數除以試驗次數,順序與輸入陣列相同。

julia> probabilities([1, 2, 3], [4, 5, 6])
3-element Vector{Float64}:
 0.25
 0.4
 0.5

3. 檢查機率的平均值

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

4. 檢查獨立事件的機率

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
透過 GitHub 編輯 連結會在新視窗或分頁中開啟
Julia Exercism

準備好開始 問題重重的機率 了嗎?

註冊 Exercism,透過 35 個概念128 個練習 和真人引導來學習並精通 Julia,全部免費。