数値の精度
コンピュータによる数値計算における精度のこと。
浮動小数点のことなどあり、計算結果に誤差が出る話し。Mathematicaを用いて計算していたところ、任意精度という概念を採用していることはこちらに書いた。Mathematicaはを『1を3等分したもの』という形で情報を持ち続けることができて、これを絶対精度と呼んでいる。
今、生起確率についての絶対精度を考える。正確確率検定においては、この生起確率の大小比較を行い、等しいもの同士は、あくまでも等しいものとして扱いたい。生起確率は、非負の整数で表現された式であるが、割り算が入っているので、下手な順番でやると、精度の影響を受けて、本当は等しいもの同士に異なる値を算出してしまう。
これの絶対精度を保持し、しかも、等しいかどうかを比較するためには、次のように考える。分子と分母はそれぞれ、整数の掛け算に過ぎないから、掛け算だけを済ませてやって、分子と分母にひとつの整数を求めて、それらを比較する、もしくは、その商を比較する。
値が小さいときは可能だが、すぐに積の算出の段階で破綻する。
では、分子と分母の掛け算の要素を比べるというのも手。しかし、これは、というのが単純で
は
のみで確定できることを利用していないので少しもったいない。
そこまで考慮するとが、浮動小数点の影響を受けるとはいえ、個々の
の計算について、固定した計算関数を用いて、四則演算の順序を固定しておき、さらに
の順も決めておけば、うまく行く。逆に言うと、これをうまくやらないと、正確確率検定の計算は、計算順序の影響を受けて『非常に』不正確になる。
この計算順序をそろえた「生起確率計算関数」はこちら
public static double lnprSortAnySize(int[][] d,double[] s){
//doubl[] s は s[k]=ln(k!)なるリスト
int[] mcol2=new int[d[0].length];
int[] mlin2=new int[d.length];
int[] tmpsix2=new int[d[0].length*d.length];
int counter=0;
int sum=0;
for(int i=0;i<d.length;i++){
for(int j=0;j<d[i].length;j++){
mcol2[j]+=d[i][j];
mlin2[i]+=d[i][j];
sum+=d[i][j];
tmpsix2[counter]=d[i][j];
counter++;
}
}
MiscUtil.sort(mcol2);//MiscUtil.sort関数は適当なソートのための関数
MiscUtil.sort(mlin2);
MiscUtil.sort(tmpsix2);
double lnpr=0;
for(int i=0;i<mcol2.length;i++){
lnpr+=s[mcol2[i]];
}
for(int i=0;i<mlin2.length;i++){
lnpr+=s[mlin2[i]];
}
lnpr-=s[sum];
for(int i=0;i<tmpsix2.length;i++){
lnpr-=s[tmpsix2[i]];
}
return lnpr;
}