2007/9/19

乱数を丸める話  VRMスクリプト禅問答
tetta氏のカメラのランダム移動がワンパターンに思える理由について。結論から申し上げますと、and命令の使い方がよろしくないから。

and命令で整数乱数を丸める(ある範囲内に収める)場合、and命令のパラメーターは二進数変換した場合にすべての桁が1になるものを使わないと、フィルター的な効果が起きてランダム度が下がります。

たとえば、
irnd vWkZ
and vWkZ,800
の場合。1行目のirnd命令で、変数vWKZには1〜1,000,000,000のいずれかの整数が入ります。で、次のand命令の800が問題なんですが、これを二進数表記に改めると1100100000になります。

and命令というのは、第一引数(上例では変数vWkZ)と第二引数(上例では800)をそれぞれ二進数に直したものを桁同士で比較して・・・

・同じ桁がどちらも1なら返り値のその桁は1。
・同じ桁のどちらか一方でも0ならば返り値のその桁は0。

とする命令です。従って、第二引数で二進数の桁が1になっていない部分は、返り値(上例ではand命令実行後の変数vWkZの値)でも常に1にはなりません。よって、irnd命令で1〜1,000,000,000の範囲の乱数を得ても、and vWkZ 800実行後のvWkZの値は、

 2進数    10進数
1100100000 = 800
1000100000 = 544
1000000000 = 512
0100100000 = 288
0100000000 = 256
0000100000 =  32
0000000000 =  0

の7通りのどれかにしかなりません、絶対に。これがワンパターンに感じられた直接の理由かと思われます。厳密に言うと、ボクはVRMの乱数のランダムさ加減については未評価なので、乱数自体がプアな可能性も否定できませんが、少なくとも上記のことはロジックから結論できます。

0〜800の範囲でランダムな値を得たいのであれば、特にtetta氏のサンプルコードのようにフライスルーカメラの座標(本来float型)として用いるのであれば・・・

rnd vWkZ
mul vWkZ 800.0
とするのが正解。rnd命令で、変数vWkZに0〜1(厳密には0.9999・・・)のいずれかの小数が得られます。これに800をかけてやれば、0〜799.9999・・・・のいずれかの値が入ります。

*     *     *

蛇足ながら、tetta氏の誤解は製品付属のスクリプトマニュアルのirndの頁にミスリードされた感もあるので、ボクはおかしいとは思いません(製品のマニュアルも、決して間違ったことが書いているワケではありませんが)。
0

この記事へのトラックバックURLはありません
トラックバック一覧とは、この記事にリンクしている関連ページの一覧です。あなたの記事をここに掲載したいときは、「記事を投稿してこのページにお知らせする」ボタンを押して記事を投稿するか(AutoPageを持っている方のみ)、記事の投稿のときに上のトラックバックURLを送信して投稿してください。
→トラックバックのより詳しい説明へ


teacup.ブログ “AutoPage”
AutoPage最新お知らせ