トラック
/
Julia
Julia
/
演習
/
厄介な確率
厄介な確率

厄介な確率

学習演習

はじめに

Rational numbersは、整数の分子を整数の分母で割った分数です。

たとえば、2//3は、近似値であるFloat64の0.6666...ではなく、正確な分数として保存できます。

利点は、(整数オーバーフローという極端な場合を除き)有理数が正確なまま保たれ、浮動小数点数ではしばしば避けられない丸め誤差を防げることです。

有理数はとてもシンプルな数値型で、みなさんが期待するとおりに動くことを目指しています。Juliaでは初期のバージョンから標準の型であるため、ほとんどの関数は整数や浮動小数点数と同じように有理数を入力として受け取ります。

有理数の作成

作成は、2つの整数の間に//を使うだけです。

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

説明

ある研究機関は、一部の若手研究者が分析で最適とは言えない手法を使っていることに気づきました。 その手法のひとつが、さらなる計算を行う前に離散確率をすぐに浮動小数点数(つまり実数)へ変換してしまうことです。

ベテランの研究者たちは、より高い精度が得られる有理数を使って計算することを好んでおり、若手研究者のこうした良くない習慣が研究の結果に影響を与えていないか知りたがっています。

行われた研究には、次の2つの種類がありました。

  • 多くのテストを実行し、それぞれが成功の離散確率を返したあと、それらの確率の平均を計算する。
  • 多くの独立した事象を試し、すべての事象が起こる全体の確率を、それらを掛け合わせて計算する。

ベテランの研究者たちは、浮動小数点数を使ったことによる丸め誤差が分析にないか判断するための関数を書いてほしい、そして誤差がある場合にはその結果を正確な有理数で示してほしいと頼んでいます。

1. 成功数と試行数の比を求める

rationalize(successes, trials)関数は、successesとtrialsの2つの配列を受け取ります。 インデックス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の2つの配列を受け取ります。 試行数に対する成功数を表す浮動小数点数の配列を、入力の配列と同じ順序で返します。

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

3. 確率の平均を調べる

checkmean(successes, trials)は、successesとtrialsの2つの配列を受け取ります。 実数の確率の平均と、有理数の確率の平均を比べます。

  • 2つの確率が同じであれば、checkmeanはtrueを返します。
  • 2つの確率が異なれば、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の2つの配列を受け取ります。 浮動小数点数の確率の全体の確率と、有理数の確率の全体の確率を比べます。

  • 2つの確率が同じであれば、checkprobはtrueを返します。
  • 2つの確率が異なれば、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を学んでマスターできます。すべて無料です。