イナヅマTVログ

あらためて言いたい、小数点計算がデキナイActionScript 3

| 1件のコメント

知っているつもりだったのに思わずハマってしまった、ActionScript 3 の小数点のワナ。

Number 型数値を乗算して int 型にしていると、「Error #1502: スクリプトがデフォルトのタイムアウト時間の 15 秒を超えて実行されました。」になったりならなかったり。
調べてみると Actionscript での小数点計算の精度に関係していることが分かった。

そういえばそんなことあったよネ、と記憶がよみがえってきた。

function numToInt(n:Number):Array {
	var p:uint = 0;
	while (!(n is int)) {
		n *= 10;
		p++;
	}
	return ([n,p]);
}
 
numToInt(1.1); // 11,1
numToInt(1.11); // タイムアウト

!(n is int) の判定部分がいつまでも false のままなのが「タイムアウト」の原因。
実際は、それ以前の処理もあり何度も自分のコードを見直したけど解明できず、やっと思い出したのが「Flash / Javascript って小数点計算はかなり怪しい」だった。

試してみた。

trace( 1.1 * 10 ); // 11
trace( 1.11 * 10 ); // 11.100000000000001
 
trace(21.3 / 3.0); // 7.1000000000000005
 
this.target_mc.alpha =0;
var k:Number = 0;
for(var i:int = 0; i < 10; i++)
{
	k += 0.1;
	target_mc.alpha += 0.1;
}
trace(k); // 0.9999999999999999
trace(target_mc.alpha); // 0.9765625

当然、Math.cos, Math.tan なんかの三角関数系にも影響しているのでしょう。
なんか不安になってきた。

小数点がつかない結果だと分っていれば toFixed(0) すれば良いけど、
除算みたいに答えに小数点がつくかもしれないと困る?

運用でなんとかできるのか?
ちっちゃいことは気にしない!でいいのか?

ちゃんと計算してくれたら悩まなくてすむのに・・・

update
「デキナイ」は言い過ぎだった。
「イケテナイ」に訂正。

1件のコメント

  1. これは、浮動小数点数が2を底にしていることに由来する挙動ですから、「イケテナイ」のは numToInt() の実装のように思えます(JavsScrip/ActionScriptに限った問題ではありません)。
    循環小数のことも考えると、精度(=仮数部 n の桁数)に上限を設けるのが妥当ではないでしょうか?
    #Cの frexp() がJS/ASにあれば、もう少しエレガントな実装が出来るんですが・・・

コメントを残す

必須欄は * がついています


このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください