« flickrでニューオリンズの台風を検索してみた | main | flash製MMO RPG、 Dofus »

2005年09月06日

Math.cos()で90度を指定すると誤差がでる件

自前のライブラリを整理していたら関数Math.cosの謎挙動を発見。

Math.cos(90*Math.PI / 180)

というようにcos90度が、6.12303176911189e-17という謎の数字を返すじゃあないですか。

Math.cos(270*Math.PI / 180)

-1.83690953073357e-16とかを返す。

つまり、どういうことかというと・・・

if(Math.cos(rad)==0)

などという条件分岐を書くと、一生trueにならないってことですよ先生。

更にこの仕様のおかげで、角度90度においては

if (val >= Math.cos(rad))

と、

if (val > Math.cos(rad))

がまったく同じ挙動を示すってことです。逆に270度のときは

if (val <= Math.cos(rad))

if (val < Math.cos(rad))

が同じ値を返してしまいます。
if文の論理式がずれるのは致命的なんじゃ・・・ というわけで三角関数で謎バグが発生する場合は、これを疑うといいかもしれません。

むねゴンさんに、チャットで「これどーなのよ!?」って聞いたら、即座に解決法を見つけてました。さすが!

投稿者 Taka : 2005年09月06日 05:41

book

dotfla.gif

bookmark

はてなブックマークに追加

del.icio.usに追加

trackbacks

this entry's trackback URL:
http://www.fladdict.net/cgi-bin/mt3/mt-tb.cgi/296

このリストは、次のエントリーを参照しています: Math.cos()で90度を指定すると誤差がでる件:

» 三角関数の誤差吸収 from 二匹狼の遠吠え
Takaさんからメッセでこんな質問が飛んできました。 「Math.cos( Ma... [read more]

トラックバック時刻: 2005年09月06日 12:33

» H57 Hoodia from h57 hoodia
[read more]

トラックバック時刻: 2006年03月27日 20:12

comment

4年近くflashを触っていながらきづかなんだ。

っていうか、これでいろんなモンのバグの原因がわかった気がする。

by Taka : 2005年09月06日 06:06

おはようございます。

この問題は、私も悩まされました。
Math.cos
Math.sin
Math.tan
三角関数は、誤差ありです。
Math.cos( Math.PI / 2 );
Math.sin( Math.PI );
Math.tan( Math.PI );
答えはすべて「0」なはずですよね^^;

私的解決法は、
・速度が必要となる場合
 (ゲームや3Dアニメーション etc... )
 この場合は、テーブルの用意をします。

・精度が必要な場合
 これは、精度にもよりますね。
 ただ、値をそのまま使っては、いません。
 丸める処理必須ですね^^;

p.s.
今気づいたんですが、リンクを触るとIEのタイトルに#moreって追加されるんですね^^;

by Anonymous : 2005年09月06日 10:13

ActionScriptでの小数はdoubleの精度なので、小数を使う計算は必ず誤差を伴います。
例えば、0.1を1万回足してみると…

by yoggy : 2005年09月07日 02:27

90度や270度はキリのいい数字に見えますけど、Math.PIをかけて浮動小数点数になった途端に誤差を伴うキリのよくない数字になります(0以外は)。
それを三角関数に渡しているんだから、キリのいい数字が返ってこなくて当然といえば当然(^^;

三角関数に限らず、浮動小数点数と整数の(範囲でなくて)ある一点とを比べるのは危険ですね。

by ooba : 2005年09月08日 15:57

うぁーい。みなさま情報ありがとうございます。
やっぱり僕は、こういうところで積み重ねの差がでちゃいますね。doubleとかfloatとか全然意識したことないからもっと勉強しないと。

by Taka : 2005年09月15日 22:38

コメントしてください




保存しますか?