メルマガ:あゆしゃのC言語プログラミング
タイトル:あゆしゃのC言語プログラミング(Vol.431) 平方根のアルゴリズム2  2004/03/05


/*========================================================*/
    <<<あゆしゃのC言語プログラミング>>>
/*========================================================*/
 第431回 平方根のアルゴリズム2
 発行    2004年3月5日(金曜日)
 発行数   約3100

{magclick}
/*========================================================*/
 はじめに ( 決り文句 )
/*========================================================*/
・このメールマガジンはまぐまぐさんから発行しています。
・ジャンルは、マルチメディアのプログラム、C言語です。
・このメールマガジンは、横60文字で作成しています。
 また、インデントはすべて半角スペース4つで構成しています。
・ここで扱うプログラムは、C言語と半光年以内のものです。
・登録解除は、まぐまぐさんのホームページでお願いします。
・まぐまぐさんのバックナンバー(下欄参照)を活用して下さい。
・ここは私の復習の場です。内容は約1ヶ月内外に私が勉強した
 内容になっています。最新の技術があれば、へたれもあります。
・わかりやすさを優先させる為、たまに嘘があるかもしれません。

/*========================================================*/
 ご挨拶
/*========================================================*/

 こんにちは。あゆしゃです。

 ドラクエがまちどうしくて、気が狂いそうな、あゆしゃです。

{magclick}
/*========================================================*/
 今回のお題  << 平方根のアルゴリズム2 >>
/*========================================================*/

 今回は、割り算を使わない、UINTの平方根を考えて見ましょう。

/*========================================================*/

 まず、平方根について基礎から確認しましょう。

 平方根とは、数字の桁数を叩き割った数字のことです。

 10000の平方根は100です。

 0x10000の平方根は0x100です。

 桁数を叩き割れば、平方根になります。

 だから、32ビットの平方根は16ビットです。

 UINTの平方根の範囲は0〜65535、たったこれだけです。

 UINTの平方根を考える場合、複雑な方程式を考える必要は
まったくありません。

 たかが6万ぐらい、総当りをかけて問題ありません。

/*========================================================*/

 6万の範囲を2分岐で検索しましょう。

UINT ayu_sqrt( UINT a );

UINT x;

// オーバーフロー例外回避
if( a >= ( UINT )65535 * ( UINT )65535 ) return 65535;

// 最初のチェック
if( a > 32768 * 32768 ) x = 32768 + 16384;
else x = 32768 - 16384;

// 残りをループ
for( chk = 8192; chk; chk >>= 1 ) {

// 大きければ大きいほうを、小さければ小さいほうを検索続行
if( a > chk * chk ) x += chk;
else x -= chk;

}

// ( UINT )sqrt( a )と答えを合わせるためのごめんなさい
if( a > x * x ) x++;
if( a < x * x ) x--;

// はい、出来上がり
return x;

/*========================================================*/

 ループは固定長なので、展開するともっと早くなります。

 標準関数のsqrt()は、大体40クロックで動作します。

 今回のこの処理はループを展開して70クロックぐらいです。

 でも、割り算を使う普通のアルゴリズムも同じぐらいです。

 割り算のくせに、早すぎです。ペンティアムはまったく。

 まぁ、柔王丸のようなマイコン製品には重宝するかも。

 なお、UINTではなくUSHORTを求める場合、40クロックぐらい、
標準関数と匹敵する速さで動作します。

 残念ながら、上回ることはありませんでした。まったく。

{magclick}
/*========================================================*/
 さいごに
/*========================================================*/

 標準関数のsqrt()は、FSQRTというアセンブラ命令を実行
します。

 つまり、電子回路で演算するわけです。

 ずるいですよね。

 ソフトでそれをシミュレートすると遅くなるのは当然ですが、
まぁ2倍弱程度なら、上出来ではないでしょうか。


 同じ感じで、浮動少数にも使えます。

 浮動少数には0という値が難しいので、

chk > 0.0000001

 という感じで、判定します。0が増えると精度が上がり、
低速化します。


 同じ感じで、巨大な桁数にも使えます。

{magclick}
/*========================================================*/
 次回予告
/*========================================================*/

 次回は3月9日(月曜日)に、第432回を送ります。
 お題は「掛け算割り算アルゴリズム」

 続いて、掛け算と割り算のアルゴリズムについて、お話でも
しましょうか。

 これも巨大な桁数計算に応用できます。

 また、32ビットの演算をサポートしない柔王丸のような
マイコン製品にも応用できるでしょうか?

 お楽しみに!

/*========================================================*/
 最後の決り文句
/*========================================================*/
 このメールマガジンは、まぐまぐさんから発行しています。
 このメールマガジンを解除したい場合は、まぐまぐさんをご利用
ください。このメルマガのまぐまぐアイディーは最後にあります。
 このメールマガジンには広告が挿入されていますか?
 このメールマガジンの内容に文面の引用はありませんか?
 めーらっくすの場合はめーらっくすの利用方に従ってください。
 このメールマガジンの内容の、転用、流用、宣伝、リンク、
暮れなずむ、野越え山越え、馬の糞 なんて大歓迎です。

{magclick}
/*========================================================*/
 
/*========================================================*/

発行者 あゆしゃ

まぐまぐアイディー
0000020674

まぐまぐバックナンバー
http://jazz.tegami.com/backnumber/frame.cgi?id=0000020674

あゆしゃの世界
http://ayusya.hp.infoseek.co.jp/

登録と解除
http://www.mag2.com/m/0000020674.htm

ご意見・ご感想・ご質問メール
mailto:ayusya@flamenco.plala.or.jp

めーらっくす <<過去ログがタイトル別になっています>>
http://www.mailux.com/mm_dsp.php?mm_id=MM3E1AEE285AB4F

ブラウザの閉じるボタンで閉じてください。