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つの種類がありました。
ベテランの研究者たちは、浮動小数点数を使ったことによる丸め誤差が分析にないか判断するための関数を書いてほしい、そして誤差がある場合にはその結果を正確な有理数で示してほしいと頼んでいます。
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
同様に、probabilities(successes, trials)関数は、successesとtrialsの2つの配列を受け取ります。
試行数に対する成功数を表す浮動小数点数の配列を、入力の配列と同じ順序で返します。
julia> probabilities([1, 2, 3], [4, 5, 6])
3-element Vector{Float64}:
0.25
0.4
0.5
checkmean(successes, trials)は、successesとtrialsの2つの配列を受け取ります。
実数の確率の平均と、有理数の確率の平均を比べます。
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の2つの配列を受け取ります。
浮動小数点数の確率の全体の確率と、有理数の確率の全体の確率を比べます。
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