Path: chuka.playstation.co.uk!news1.scei.co.jp!usenet From: Psuke Newsgroups: playstation.ny.program.questions Subject: Re: =?iso-2022-jp?B?GyRCIzJFQDRWJE41d04lJHJJYkYwPi4/dEVAJHI7SCRvGyhC?= =?iso-2022-jp?B?GyRCJDokSzVhJGEka0p9SyEbKEI=?= Date: Mon, 20 Apr 1998 05:28:20 +0900 Organization: PlayStation Net Yarouze Lines: 87 Message-ID: <353A5E63.9B98A698@mxz.meshnet.or.jp> References: <6hd9hg$m3d@news1.scei.co.jp> NNTP-Posting-Host: 133.205.180.121 Mime-Version: 1.0 Content-Type: text/plain; charset=iso-2022-jp Content-Transfer-Encoding: 7bit X-Mailer: Mozilla 4.05 [ja] (Win95; I) どうもPsukeです。 僕の知っている方法を書きましょう。 他の方でちがう方法を知っていれば教えてください。 Sugihara Yoshimi wrote: > sugiharaといいます。 > > long型であらわされた座標(x、y)で、2点間の距離を浮動小数点を使わず > に求める方法はないでしょうか? > > 実は、ある位置からある目標に対しての回転行列を求めるときに必要になるのです > が、浮動小数点を使うとやたら遅くなるので困っています。 > この時の、計算方法は以下のようにしています。 > > x = px - qx > y = py - qy > > r = (long) sqrt( (double) ( (x*x) + (y*y) ) ) ・・・・sqrtを使う > と重たくなる。(;; > > c = x / r > s = y / r > > MATRIX mrx > > mrx.m[0][0] = c mrx.m[0][1] = -s mrx.m[0][2] = 0 > mrx.m[1][0] = s mrx.m[1][1] = c mrx.m[0][2] = 0 > mrx.m[2][0] = 0 mrx.m[2][1] = 0 mrx.m[0][2] = 1 > > て感じにしてます。 > > ご存知の方、ヒントだけでも良いので教えてください。 > > よろしくお願いします。 上を見るに キャストしてあるので sqrt が悪いのが理解できてるようですね。 まず、1つ目はこのsqrtを返り値がlong型になるよう自分で書き直します。 long Lsqrt(long a){ long s1,s2; //エラー処理は省いてます。 do{ s2 = s; s = (a / s + s)/2; }while(s != s2); return s; } です。しかし非常に制度が悪いです。 Lsqrt(99) == 9ですわ。 そこでもうひとつ http://www02.so-net.ne.jp/~einsidle/reversible/ 内にある僕の作った3D版Hi-Jump demo(2D版もあるので間違えないでね) にkotei2.cというソースコードがくっついてだいぶ前からアップされています。 kotei2.cというのは固定小数点を扱うための関数です。 固定小数点とは(僕も最近まで知らなかった)ある数字を1と考えます。 kotei2.cでは4096を1と考えてます。 例えば、(double)0.5は(long)2048です。 では実際に上のプログラムをkotei2.cを使って書き換えると //////////////////////////////////////////// x = (px - qx) << 12;//固定小数点を使うため4096倍する y = (py - qy) << 12;//固定小数点を使うため4096倍する r = Kotei_Sqrt( Kotei_Kakeru(x,x) + Kotei_Kakeru(y*y) ) ; c = Kotei_Waru(x , r); s = Kotei_Waru(y , r); MATRIX mrx 固定小数点が必要なくなったので4096で割る。 mrx.m[0][0] =c>>12; mrx.m[0][1] = -(s >>12);mrx.m[0][2] = 0; mrx.m[1][0] =s>>12; mrx.m[1][1] = c>>12 ;mrx.m[0][2] = 0; mrx.m[2][0] = 0 ; mrx.m[2][1] = 0 ;mrx.m[0][2] = 1; /////////////////////////////////////// となりかなり高速化できるはずです。 もちろん最後の「固定小数点が必要なくなったので4096で割る」は その後も固定小数点を使うなら割る必要はないですし cやsが4096以下なら0になるのでその後も固定小数点を使わないと 計算した意味がありません。 以上分かりにくい説明でしたが、ということです。 Psuke p_suke@mxz.meshnet.or.jp