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

2007/9/20  2:34

投稿者:tetta
再度のご指南有難う御座います。
マニュアルの例は、お師匠様(勝手にすいません)のおっしゃる通りですね。
たま〜に載ってるサンプルは間に受けて使ってしまうのがパターンかと。
本家スクリプトマニュアルも、もう少し整備した方がスクリプトにチャレンジしようって人が増えるような気がします。

えっ!「エキスパートガイド」買えって。私は0号入手時に読破してま〜す。(笑)

2007/9/19  6:35

投稿者:ghost
> floatに整数をぶち込んで大丈夫なものか?
>(問題有りの記事を見たような・・・)

VRMの仕様(の正が何であるかはさておき)上は、int・float変換は自動らしいですが、ある時点までは不完全でした。たとえば、setf命令に小数点とそれ以下を含まない整数を与えると0として評価される、等の不具合がありました。

これが、どこかのアップデータで改善されたみたいです。いつだったか、は、ちょっとよくわかりませんけども。

ただ、これが本当に理想的に動作しているかどうかは怪しいので、ある程度以上複雑なスクリプトを組む人は、intとfloatは意識して使い分けた方が良い、と個人的には思っています。計算精度の問題とかもあるので。

ちなみに、整数乱数を任意の範囲で得たい場合は、and命令ではなくてmod命令を使うといいです。たとえば、0から800の範囲で整数乱数を変数aに得るのであれば、

irnd a
mod a 801

でOK。っつーか、マニュアルにはこっちの例を載せるべきなんじゃないかと思います。まぁ、範囲指定によってはちょっと偏りますけど、誰も気にしないでしょう、そんなこと。

2007/9/19  3:41

投稿者:tetta
やられた〜!(マニュアル)。言われてみれば仰る通り。流石にお師匠様はツッコミが深いです。
私の世界ではirndなる物は無く、必然的に後者で行うのですが、理論整然と説明頂くと確かに安易っであったと気づかされます。www
別の意味でもfloatに整数をぶち込んで大丈夫なものか?(問題有りの記事を見たような・・・)という思いもあったのですが、少なくとも座標に関しては使えるようですが。(お師匠様は流石にキッチリfloatを使ってるのを今更確認・・・やっぱりfloatを使おう)(笑)
しかしirnd・・・使い道が限定されそーな?(分かり易さが主か?)

ブックマーク参考にしてみます。感謝!

コメントを書く

この記事にはコメントを投稿できません




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