10周年のSPコンテンツ!

吉里吉里2/Z 乱数不具合

Math.random()で1.0が出る問題。 吉里吉里2では出ないと報告にあったが、周期が長いので表面化していなかっただけの模様。
ゲーム 吉里吉里
0
じん @jin1016
場当たり的対処のpull requestだな…… github.com/krkrz/krkrz/pu…
じん @jin1016
吉里吉里2(TJS2)をgccでコンパイルしようとしても発生する潜在的不具合だけど、そもそもコンパイル通らないだろうし、考慮もほとんどされていないから、吉里吉里Zの問題だな……
じん @jin1016
違う、違う。 動作的にはどっちも同じだ。 吉里吉里2でも同じように1を含む動作になってるんじゃないかな
じん @jin1016
Math.randomの見て最初に思ったんだけど、みんなMath.RandomGeneratorの方しか使わないと勝手に思ってた。まあ、暫定とかでMath.random使うことはあるとしても、リリースする版には入れないとか言う勝手な認識。
みあみい @miahmie
@jin1016 自分もRandomGenerator使ってますが,KAG由来のUtils.tjsにあるintrandomとかrandomプロパティはMath.random実装ですね・・・
じん @jin1016
@miahmie やはりRandomGenerator使いますよね。でも、KAGで使っている部分があったとは……
じん @jin1016
Math.randomが使われるのなら乱数の周期などがコンパイラによって変わってしまうのは好ましくないかもしれないなぁ。xorshiftなどに置き換えてしまった方がいいかも
じん @jin1016
_lrand のソースアセンブリかよと思ったけど、最後& 0x7fffffffしてるし、やっぱり1を含みそうな感じだよな
じん @jin1016
@nyanyashi 吉里吉里2ですか? だとしたら、仕様と実装が元々違っていたと言うことですね。
じん @jin1016
@nyanyashi じゃあ、やはり元々あった不具合なんですね。
じん @jin1016
@yunyundetective @nyanyashi でも、今まで誰も気付いていなかった件
ゆんゆん探偵 @yunyundetective
@jin1016 @nyanyashi *result = ((tTVReal)((tTVReal)TJS_rand()/(tTVReal)(TJS_RAND_MAX))); これは確かに1が出る。
ゆんゆん探偵 @yunyundetective
@jin1016 @nyanyashi 「1未満」にしようと思ったら、 こうですかね。 *result = ((tTVReal)((tTVReal)TJS_rand()/((tTVReal)(TJS_RAND_MAX)+1)));
じん @jin1016
@yunyundetective @nyanyashi ほぼ同じpull requestが来ています。 github.com/krkrz/krkrz/pu… 吉里吉里2では出ないと言うので、色々とソースコード追ったりしていました。
にゃにゃし候補生 @nyanyashi
あ゛ー、見返したらMath.random()使ってて1.0が出たら落ちるところ一か所だけあった…orz
ゆんゆん探偵 @yunyundetective
@jin1016 @nyanyashi 配列からのランダムセレクションに使うと範囲外アクセスでエラーが出るパターンがありますねえ。
ゆんゆん探偵 @yunyundetective
@jin1016 @nyanyashi ちなみにMTのRandomGeneratorのソースでは、浮動小数点のビットパターン自体に乱数を埋め込んで理論上あり得る「0以上1未満」の数のどれかを作るアルゴリズムになっているので問題ないようです。
にゃにゃし候補生 @nyanyashi
@jin1016 @yunyundetective すんごい確率低いですからね…1104774470回目と1510578330回目で出ましたいまのところ。
ゆんゆん探偵 @yunyundetective
@nyanyashi @jin1016 RAND_MAXって環境によって値が違うのですがその分だと吉里吉里のBC環境だと 0x7FFFFFFF くらいあるですかね?
じん @jin1016
@nyanyashi @yunyundetective 数が多すぎてパッと見てわからないですねw 吉里吉里2の_lrandは2^64周期と言うことなので長いです。
ゆんゆん探偵 @yunyundetective
@jin1016 @nyanyashi 64乗…そりゃ長い。表面化しないわけだ。
じん @jin1016
吉里吉里2 では、bcc の _lrand が使われているので、Math.randum() は 2^64周期。吉里吉里Z は、vc の rand だから 16ビットくらいかな
残りを読む(2)

コメント

コメントがまだありません。感想を最初に伝えてみませんか?

ログインして広告を非表示にする
ログインして広告を非表示にする