Onegame

Flash 9のスクリプト言語ActionScript 3.0の技術情報とゲームの開発


トップページ - TIPS

高品質乱数 メルセンヌツイスター(Mersenne Twister)

高品質な疑似乱数アルゴリズムとして有名なMersenne Twisterです。
ゲームに高い品質の乱数が求められることがあるかはわかりませんが、 このサイトではモンテカルロ法等を使用したプログラムも作っていく予定なので、 ActionScript 3.0に移植しました。

乱数に高い品質を求める理由が特にない場合は付属のMath.random()メソッドを使う方が手軽かもしれません。

参考URL : Mersenne Twister : A random number generator

以下使い方、実行例、メルセンヌツイスタークラスのソースプログラムです。

使い方
var mt:MersenneTwister; var rand:Number; mt = new MersenneTwister(0); rand = mt.nextNumber();

実行例
※ このFlashを見るにはFlash Player 9が必要です。

ソースプログラム MersenneTwister.as

package
{
    public class MersenneTwister
    {
        private const N:int = 624;
        private const M:int = 397;
        private const UPPER_MASK:uint = 0x80000000;
        private const LOWER_MASK:uint = 0x7fffffff;
        private const MATRIX_A:uint   = 0x9908b0df;
        private var x:Array;
        private var p:int;
        private var q:int;
        private var r:int;
        
        public function MersenneTwister(s:uint) {
            x = new Array();
            seed = s;
        }
        
        public function set seed(s:uint):void {
            x[0] = s;
            for (var i:int = 1; i < N; i++) {
                x[i] = imul(1812433253, x[i - 1] ^ (x[i - 1] >>> 30)) + i;
		x[i] &= 0xffffffff;
            }
            p = 0;
            q = 1;
            r = M;
        }
        
        /**
         * [0, 1)
         */
        public function nextNumber():Number {
            return next(32) / 4294967296;
        }
        
        private function next(bits:int):uint {
            var y:uint = (x[p] & UPPER_MASK) | (x[q] & LOWER_MASK);
            x[p] = x[r] ^ (y >>> 1) ^ ((y & 1) * MATRIX_A);
            y = x[p];
            
            if (++p == N) {p = 0;}
            if (++q == N) {q = 0;}
            if (++r == N) {r = 0;}
            
            y ^= (y >>> 11);
            y ^= (y << 7) & 0x9d2c5680;
            y ^= (y << 15) & 0xefc60000;
            y ^= (y >>> 18);

            return y >>> (32 - bits);
        }

        private function imul(a:Number, b:Number):Number {
            var al:Number = a & 0xffff;
            var ah:Number = a >>> 16;
            var bl:Number = b & 0xffff;
            var bh:Number = b >>> 16;
            var ml:Number = al * bl;
            var mh:Number = ((((ml >>> 16) + al * bh) & 0xffff) + ah * bl) & 0xffff;
            
            return (mh << 16) | (ml & 0xffff);
        }
    }
}

copyright onegame.bona.jp