メルマガ:あゆしゃのC言語プログラミング
タイトル:あゆしゃのC言語プログラミング(Vol.453) 平方根デバッグ  2004/05/26


/*========================================================*/
    <<<あゆしゃのC言語プログラミング>>>
/*========================================================*/
 第453回 平方根デバッグ
 発行    2004年5月26日(水曜日)
 発行数   約2900

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

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

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

/*========================================================*/
前回までのあらすじ

 先日、といっても昔のことではなく本当に最近なのですが、FBを
やっていたとき、

「すばやさアルゴリズムは、どうなっているのだろう?」

 と、疑問に思いました。さっそくグーグルで、

 「フfァaントムブレイブ+アルゴリズム」で検索しても、それら
しいものは良くわかりませんでした。

 他のキーワードでも、良くわかりませんでした。

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

 すばやさが90,80,30のとき、行動回数は9:8:3に
なって欲しいところが人情という感じでしょう。

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

 一番簡単そうなのは、最小公倍数を使う方法でしょうか。

 つまり、すべての参加キャラの最小公倍数を求め、誰か1人が
その値を超えるまで、自分たちのすばやさを加算していき、上回っ
たら、そいつが動いて、すばやさの現在値を0にリセット。

 という感じでいいような気がしますが、最小公倍数なんて、INT
の32ビットを簡単に超えてしまうので、少し無理でしょうか。

 足し算のみとはいえ、ループの回数が多そうですし、。。。、
これはだめかなぁ?

 うーん、困った。

/*========================================================*/
というわけで

 とりあえず、最小公倍数はどのように求めるのでしょうか?

 2つの値の最小公倍数を求めるには、2つの値が同じになるまで
低いほうの値を増してやればよいのです。つまり、

while( a != b ) {
    if( a < b ) a += a_base;
else b += b_base;
}

 という感じ。基本的には、ですけどね。
 _base は、元の値です。

{magclick}
/*========================================================*/
 今回のお題  << 平方根デバッグ >>
/*========================================================*/

 前回までで、大型計算機は足し算と引き算と掛け算と割り算が
行えるようになりました。

 ならば平方根、と勇んで実行すると、撃沈。。。

 帰ってこなくなります。

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

 UINT のときの計算回数は、16回ぐらいでした。ビット数の、
半分と同じぐらいだからです。

 大型計算機は8192ビットですから、計算回数は4096回
ぐらいです。

 この回数だけ、掛け算と比較と足し算または引き算が動きます。

 計測した結果、掛け算が死ぬほど遅いということが分かりまし
た。

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

 その前に、計算回数を減らしましょう。少し、多すぎます。

CXInt& CXInt::sqrt( void )
{
    CXInt a( *this ); // 自分を複製
    int pos = SIZE * 8 / 2; // 限界値のビット位置

    // 最初の比較(オーバーフローチェック)
    clear().setBit( pos-- ).dec(); // x = 65535
    if( a.cmp( copy().pow() ) >= 0 ) return *this; // ret 65

    // 自分を初期化
    clear().setBit( pos-- ); // x = 32768

    // 2回目以降の比較
    for( ; pos; pos-- ) {
        if( a.cmp( copy().pow() ) > 0 ) add( CXInt().setBit(
        else sub( CXInt().setBit( pos ) );
    }
    if( a.cmp( copy().pow() ) > 0 ) inc();
    if( a.cmp( copy().pow() ) < 0 ) dec();
    return *this;
}

 最初のビット位置を、最大位置にしていますが、これを間引き
しましょう。

    CXInt a( *this ); // 自分を複製

    // 最初の比較(オーバーフローチェック)
    clear().setBit( SIZE * 8 / 2 ).dec(); // x = 65535
    if( a.cmp( copy().pow() ) >= 0 ) return *this; // ret 65

    // 最初の計算位置を求める
    CXInt mask;
    int pos = 0;
    mask.setBit( pos );
    while( pos < SIZE * 8 - 1 && a.cmp( mask ) > 0 ) {
        mask.setBit( pos, 0 );
        pos++;
        mask.setBit( pos );
    }
    mask.setBit( pos, 0 );
    pos = pos / 2 + 1;

// 自分を初期化
clear().setBit( pos-- ); // x = 32768

    // 2回目以降の比較
    mask.setBit( pos );
    CXInt c( *this );
    c.pow();
    for( ; pos >= 0; pos-- ) {
        if( a.cmp( c ) > 0 ) add( mask );
        else sub( mask );
        mask.setBit( pos, 0 );
        mask.setBit( pos - 1 );
        c.set( *this ); // copy
        c.pow();
    }
    if( a.cmp( copy().pow() ) > 0 ) inc();
    if( a.cmp( copy().pow() ) < 0 ) dec();
    return *this;

 という感じにしてみましょう。
 前半のループは、最大のビット位置を検索しています。

 後半のループでは、少し早くなるように、マスクを大事に計算
するようにしました。

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

 かなり早くなりましたが、答えが違います。がーん。

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

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

 次回は5月28日(金曜日)に、第454回をお送りします。
 お題は「平方根のデバッグ2」

 お楽しみに!

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

{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

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