【WEBアプリ】ハナハナホウオウ天翔の設定判別ツール
【WEBアプリ】ハナハナホウオウ天翔の設定判別ツール
※ご使用は自己責任でお願いいたします。
差枚数からベル確率を逆算して、その分も設定推測に反映してます。
設定値は下の方にあるスペック表の値でいじれるようにしているので、ご自身で適当な値に修正してください。
(特にベル・スイカ・チェリー確率は予想値なので間違ってる可能性大です。→予想した時の記事)
(差枚数からベル確率を算出するツールは→こちら)
スペック表(いじると設定判別結果に反映されます。)
確率 | 設定1 | 設定2 | 設定3 | 設定4 | 設定5 | 設定6 |
---|---|---|---|---|---|---|
BB確率 | ||||||
RB確率 | ||||||
チェリー確率 | ||||||
スイカ確率 | ||||||
ベル確率 |
・ツールの解説
やってることはこのあたりの記事と同じで、二項分布確率を求めてるだけです。
が、プログラムを作成する上でちょっと感動したことがあったので、そこだけ説明したいと思います。
(これもプログラムに詳しい人なら当たり前のことかもしれませんが、、)
まずは、二項分布確率ってどんな計算式だったのかというと、
nCxpx(1 - p)n-x = n! / [x!(n - x)!]px(1 - p)n-x
こうですね。(カッコの順番って"("→"{"→"["って習った気がするけど、いつ変わったんだろ。)
例えば、コインを4回投げて2回表が出る確率は、表が出る確率を50%(=0.5)とすると、
4C20.52(1 - 0.5)4-2 = 4! / [2!(4 - 2)!]0.52(1 - 0.5)4-2
で求めることができます。(面倒なので計算しませんが。)
で!コーディングする時に問題になるのが、「!(階乗)」の部分です。
(階乗っていうのは、4!=4×3×2×1って計算するやつ。)
今回みたいに4回とかなら良いですが、我々スロッターの試行回数ってそんなもんじゃなく、1000回や2000回は当たり前で、なんなら8000回とか試行するわけで。。
そうすると、8000の階乗とか計算しなきゃいけなくなるんです。
ちなみに、8000!=5×1027752になるらしいですが、JavaScriptでは倍精度浮動小数点数型と呼ばれる数値データ型が使われているそうで、ざっくり20桁くらいの数字を持つことができるわけですが、これでは全然足りません。
(こういうのを桁あふれとかオーバーフローっていうみたいです。)
最終的には、似たような桁数の割り算があるので桁あふれしない程度の数値になりますが、プログラムで順番に計算していこうとすると序盤の階乗で桁あふれしてしまって計算できなくなってしまいます。
そこで、対数(log)を使います。
対数っていうのはあれですね、100は10の2乗ですっていうのをlog10100=2って表すやつです。
これが何の役に立つかというと、掛け算が足し算になるんです!
例えば、10×100=1000になりますよね。これが対数だと、
log1010+log10100=1+2=3
となって、足し算で計算できるようになります。
で、最終的に出てきた値を103のように元の数値に戻せば答えを得ることができます。
(ちなみに、割り算は引き算、二乗とかのn乗の計算は掛け算になります。)
ということで、実際にJavaScriptでコーディングしていきましょう。
あ、log10みたいな感じで底を10で説明しましたが、コーディングは底をネピア数(ネイピア数?)でやってます。
とりあえず条件は適当に、1/250の確率のBBを8000回転で30回引く確率を算出していきます。
//入力値を設定
bbprob = 1/250;
play = 8000;
bb = 30;
n! / [x!(n - x)!]px(1 - p)n-x
まずは赤字の階乗の部分、8000回転の階乗を行います。
先ほど説明したとおり、対数を使えば掛け算は足し算でOKなので、1+2+3+...+8000を計算すればOKです。(厳密にはlog(1)+log(2)+...)
つまり、for文を8000回ループしながら足し算すればOKってことですね。
//階乗の計算(n!の部分)
var factpl = 0;
for (i = 1;i <= play;i++){
factpl = factpl + Math.log(i);
}
n! / [x!(n - x)!]px(1 - p)n-x
この辺の青とか緑の階乗も同じですね、for文をループする回数を変えればやることは同じです。
//階乗の計算(x!の部分)
var factbb = 0;
for (j = 1;j <= bb;j++){
factbb = factbb + Math.log(j);
}
//階乗の計算((n-x)!の部分)
var factpb = 0;
for (k = 1;k <= play - bb;k++){
factpb = factpb + Math.log(k);
}
n! / [x!(n - x)!]px(1 - p)n-x
次にオレンジやピンクのn乗の部分。
対数ではn乗の計算は掛け算になるので、シンプルに掛け算すればOKです。
//n乗の計算(p^xの部分)
bbprobpow = Math.log(bbprob) * bb;
//n乗の計算((1-p)^(n-x)の部分)
mibbprobpow = Math.log(1 - bbprob) * (play - bb);
最後にそれぞれの項目を割ったり掛けたりして二項分布確率の最終結果を求めます。
対数では割り算が引き算、掛け算が足し算なので、こんな感じになります。
あ、最後にexpを使って対数から元に戻すのを忘れずに。
//二項分布確率の最終結果
pnkbb = Math.exp(factpl - factbb - factpb + bbprob + bbprobpow + mibbprobpow);
ここまでのコードをまとめて書くとこんな感じです。
普通に階乗を掛け算するとオーバーフローする計算でも、対数を使うことで計算できるようになります!
//入力値を設定
bbprob = 1/250;
play = 8000;
bb = 30;
//階乗の計算(n!の部分)
var factpl = 0;
for (i = 1;i <= play;i++){
factpl = factpl + Math.log(i);
}
//階乗の計算(x!の部分)
var factbb = 0;
for (j = 1;j <= bb;j++){
factbb = factbb + Math.log(j);
}
//階乗の計算((n-x)!の部分)
var factpb = 0;
for (k = 1;k <= play - bb;k++){
factpb = factpb + Math.log(k);
}
//n乗の計算(p^xの部分)
bbprobpow = Math.log(bbprob) * bb;
//n乗の計算((1-p)^(n-x)の部分)
mibbprobpow = Math.log(1 - bbprob) * (play - bb);
//二項分布確率の最終結果
pnkbb = Math.exp(factpl - factbb - factpb + bbprob + bbprobpow + mibbprobpow);
console.log(pnkbb);
いやー、これ凄くないですか?
学生の時は「対数。あ、そうなんですね。」くらいで全く興味が湧きませんでしたが、こうやって便利な使い方を知ると興味が湧いてきます。
そういえば、学生時代にフーリエ変換を習った時に、学校の先生から「これを使うとデータの圧縮ができます。」って説明されて興味をもって勉強できたことを思い出しました。
まあ対数って中学か高校くらいに習った気がするので、「君たち、対数ってスロットで便利なんだよ。」って説明されても興味持ってなかったと思いますが。
コメント
コメントを投稿