メルセンヌツイスタによる擬似乱数アルゴリズムのテスト
Math.random() を使わない乱数の取り方があるみたいなので、ちょっと真似してます。
♥0 |
Line 125 |
Modified 2012-01-04 21:19:22 |
MIT License
archived:2017-03-09 23:50:19
ActionScript3 source code
/**
* Copyright syake ( http://wonderfl.net/user/syake )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/7LkM
*/
/*
Mersenne Twisterのライセンスに依ります。2012年1月現在、修正BSDライセンスです。
Mersenne Twister
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/mt.html
hakuhinさんのサンプルコードを参考にしています。
http://hakuhin.jp/as/random.html#RANDOM_03
*/
package {
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.text.TextField;
import flash.text.TextFormat;
/**
* メルセンヌツイスタによる擬似乱数アルゴリズムのテスト
* @version Flash Player 9.0.124
* @ActionScriptversion ActionScript 3.0
* @author Hiroaki Komatsu
* @see http://hakuhin.jp/as/random.html#RANDOM_03
* @see http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/mt.html
*/
public class MersenneTwisterTest extends Sprite {
// --- property
private var clearBitmap:BitmapData;
private var point:Point;
private var bitmap:BitmapData;
/**
* constructor
*/
public function MersenneTwisterTest() {
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
public function init(e:Event = null):void {
removeEventListener(Event.ADDED_TO_STAGE, init);
var w:uint = stage.stageWidth;
var h:uint = stage.stageHeight;
// 初期設定
clearBitmap = new BitmapData(w, h, true, 0x0);
point = new Point(0, 0);
this.graphics.beginFill(0x0);
this.graphics.drawRect(0, h, w, 1);
this.graphics.endFill();
// 疑似乱数
bitmap = clearBitmap.clone();
addChild(new Bitmap(bitmap));
var txt:TextField = new TextField();
txt.defaultTextFormat = new TextFormat("_等幅", 10, 0x666666);
txt.height = 20;
txt.selectable = false;
txt.autoSize = "left";
txt.text = "※ステージをクリックしてください";
txt.x = 10;
txt.y = 10;
addChild(txt);
// イベントリスナー登録
stage.addEventListener(MouseEvent.MOUSE_DOWN, touch);
}
/**
* 疑似乱数の取得
* @param event
*/
private function touch(event:MouseEvent):void {
// クリア
bitmap.copyPixels(clearBitmap, clearBitmap.rect, point);
// 描画
var x:uint, y:uint;
for (var i:uint = 0; i < 100; i++) {
x = Math.floor(MersenneTwister.getFloat() * bitmap.width)
y = Math.floor(MersenneTwister.getFloat() * bitmap.height);
draw(bitmap, x, y, 0xFF0000FF);
}
}
/**
* 描画
*/
private function draw(bitmap:BitmapData, x:uint, y:uint, color:uint):void {
bitmap.setPixel32(x-2, y , color);
bitmap.setPixel32(x-1, y , color);
bitmap.setPixel32(x , y-2, color);
bitmap.setPixel32(x , y-1, color);
bitmap.setPixel32(x , y , color);
bitmap.setPixel32(x , y+1, color);
bitmap.setPixel32(x , y+2, color);
bitmap.setPixel32(x+1, y , color);
bitmap.setPixel32(x+2, y , color);
}
}
}
class MersenneTwister {
// --- const
static private const MT_N:uint = 624;
static private const MT_M:uint = 397;
static private const MATRIX_A:uint = 0x9908b0df;
static private const UPPER_MASK:uint = 0x80000000;
static private const LOWER_MASK:uint = 0x7fffffff;
// --- property
static private var mt_obj:Object;
{
mt_obj = initialize(0);
}
/**
* 初期化
* @param seed
* @return Object {uint,Array}
*/
static private function initialize(seed:uint):Object {
var a:uint,b:uint,al:uint,ah:uint,bl:uint,bh:uint,cl:uint,ch:uint;
var mti:uint = MT_N + 1;
var mt:Array = new Array();
mt[0] = seed & 0xffffffff;
for (mti = 1; mti < MT_N ; mti++) {
a = 1812433253;
b = mt[mti-1] ^ (mt[mti-1] >>> 30);
al = a & 0xFFFF;
ah = a >>> 16;
bl = b & 0xFFFF;
bh = b >>> 16;
cl = (al * bl) + mti;
ch = (cl >>> 16) + ((al * bh) & 0xFFFF) + ((ah * bl) & 0xFFFF);
mt[mti] = ((ch << 16) | (cl & 0xFFFF));
mt[mti] &= 0xffffffff;
}
return {
mti : mti,
mt : mt
};
}
/**
* -2147483648 ~ 2147483647 までの乱数を取得
* @return int
*/
static public function getInt32():int {
var obj:Object = mt_obj;
var y:int;
var mag01:Array = [0x0, MATRIX_A];
if (obj.mti >= MT_N) {
var kk:uint=0;
if (obj.mti == MT_N+1) obj = initialize(5489);
for (;kk < MT_N - MT_M; kk++) {
y = (obj.mt[kk] & UPPER_MASK) | (obj.mt[kk+1] & LOWER_MASK);
obj.mt[kk] = obj.mt[kk+MT_M] ^ (y >>> 1) ^ mag01[y & 0x1];
}
for (;kk < MT_N-1;kk++) {
y = (obj.mt[kk] & UPPER_MASK) | (obj.mt[kk+1] & LOWER_MASK);
obj.mt[kk] = obj.mt[kk+(MT_M-MT_N)] ^ (y >>> 1) ^ mag01[y & 0x1];
}
y = (obj.mt[MT_N-1] & UPPER_MASK) | (obj.mt[0] & LOWER_MASK);
obj.mt[MT_N-1] = obj.mt[MT_M-1] ^ (y >>> 1) ^ mag01[y & 0x1];
obj.mti = 0;
}
y = obj.mt[obj.mti++];
y ^= (y >>> 11);
y ^= (y << 7) & 0x9d2c5680;
y ^= (y << 15) & 0xefc60000;
y ^= (y >>> 18);
return y;
}
/**
* 0 ~ 0.999999…までの乱数を取得
* @return Number
*/
static public function getFloat():Number {
var r:Number = getInt32()*(1.0/4294967296.0);
if(r < 0) r += 1.0;
return r;
}
}