パスワードを忘れた? アカウント作成
この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。

「カルドセプトサーガ」にダイス目が偶数と奇数を繰り返すバグ」記事へのコメント

  • by Anonymous Coward
    法則を入れる方が面倒じゃないのか?
    何でこんなことになったの?
    • Re:理解できん (スコア:5, 参考になる)

      by niratama (2175) on 2006年12月06日 14時05分 (#1070443) ホームページ 日記
      メルセンヌ・ツイスタのページからリンクされていた、良い乱数・悪い乱数 [so-net.ne.jp]によると、

      rand( )その1

      UNIX の /usr/ucb/cc、gcc、g++を解析した結果、 rand( ) は以下の動作をすることがわかった。

      static long x=1;
      void srand(unsigned s) { x=s; }
      long rand() { x=x*1103515245+12345; return x&2147483647; }

      これは、非常にシンプルな線形合同法である。この乱数の最下位ビットは0と1の繰り返しになる。すなわち、偶数と奇数が交互に生成される。このことから、この乱数で下位ビットを乱数として使うのは危険であることがわかる。また、ある乱数が得られたら、次に現れる乱数が1種類しかないという欠点も持つ。

      だそうで、まさにこれが原因じゃないでしょうか。
      親コメント
      • Re:理解できん (スコア:2, 参考になる)

        by gnaka (17369) on 2006年12月06日 15時57分 (#1070533) 日記
         rand() % 6 + 1 とでもしたということですかね。
         もしrand()が [0,1) のdoubleを返していたら、定番の「6を掛けて整数に切り捨て1を足す」というイディオムを使わざるを得ず、こういうバグは起きなかった。乱数を返す関数に小数を返す言語が多いのはこのあたりが理由ですかねえ。

         ちなみに、ワードサイズ w (例えば2^31)の計算機における x[n+1] = ( a * x[n] + c) mod m の線形合同法について、Knuth翁は、m = w では最下位ビットは「定数になるか、確実に交代する」(やや不自然な訳)ので m = w±1 の方が望ましいが、
        ほとんどの応用では、下位ビットは重要な意味をもたず、m = wとしても満足できる。――ただし、乱数を使うプログラマが乱数を賢く使うことを前提としてである。
        といわれております。
        『The Art of Computer Programming Volume 2 Seminumerical Algorithms 日本語版』Donald E. Knuth著、有沢誠他監訳
        親コメント
      • by scavenger (21990) on 2006年12月06日 19時11分 (#1070678)
        まさにこれに遭遇したことが。

        skiplistを試してみたとき、リストの深さを決定するのに、
            while(rand()%2==1) {
                level++;
            }
        みたいなことをしたんですが、深さは0が1しか得られませんでした。
        おかげでskiplistなのに遅い遅い(笑)

        NetBSD1.6のころだったっけ。
        linuxでは一応期待したように動きましたが、rand()%2はアレなので止めました(笑)
        親コメント
      • 何も考えず(←これはこれで問題だが)常に Mersenne Twister を使ってます、自分。
        自分で C++ のクラス使ってたら、あっさりと boost::random [kmonos.net] に含まれていることに気づいた。boost のせい(おかげ)で自作のクラスライブラリの結構な部分が不要になってうれしいような悲しいような。まぁ自分で作った糞ライブラリよりも
        えらい人が作ってえらい人がレビューしたライブラリの方が信頼性が高い(はずな)ので良し!とするか。

        #えらい人が増えれば増えるほど、自分(と自分のやった仕事)が
        #不要になっていくので人類の進歩は自分の存在価値と相反するのだと
        #気づいた今日この頃。えらい人が糞な仕事で忙殺されないように
        #雑用こなすのが使命と気づいた。それすら満足にこなせてないが orz
        --
        屍体メモ [windy.cx]
        親コメント
      • by Anonymous Coward
        たしかX68000のXC1もこれだったな…とか思い出してみる。

        最近のアルゴリズムでは、メルセンヌ・ツイスターがけっこう良かった気がする。
      • by Anonymous Coward
        FreeBSD(手元のは5-STABLE)のrand(/usr/src/lib/libc/stdlib/rand.c)には"Historic implementation compatibility."としてそのコードが残ってます。でも、USE_WEAK_SEEDINGを定義しないと有効にならず、実際に使われているのは

                long hi, lo, x;

                /* Can't be initialized with 0, so use another value. */
                if (*ctx == 0)
                        *ctx = 123459876;
                hi = *ctx / 127773;
           

Stay hungry, Stay foolish. -- Steven Paul Jobs

処理中...