HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2014
0201
ZAPrnd関数で発生させる乱数のパターンについて8解決


ZAP

リンク

2014/2/1(Sat) 10:25:24|NO.59586

rnd関数で得られる乱数のパターンについては、randomize命令のヘルプに


randomize p1 p1に同じ値を指定して初期化された乱数は、 常に同じパターンで乱数を発生させられます

と、ヘルプにはありますが、
これは、OS等、実行環境が異なる場合でも保証されているのでしょうか?

現在、STGの敵の攻撃パターンにrndを使っている箇所があり、
リプレイ時にも同じパターンが再現されるよう、
プレイ時にrandomizeの初期化の値(seed値)を保存しておき、
リプレイ再生時には同じseed値により乱数を初期化することで
プレイ時と同じ敵の挙動を再現する、という手法を取っているのですが、
記録時と再生時の環境が異なると結果が変わるのであれば、
自前の疑似乱数を用意するといった代替手段が必要だろうと考えています。



この記事に返信する


kanahiron

リンク

2014/2/1(Sat) 10:32:06|NO.59587

自作の画像ビューアをAndroidに移植しましたが、
randomizeで同じ引数を指定しても発生する乱数はwindowsとandroidで異なりました
windowsならwindowsと、AndroidならAndroidで同じパターンは発生するのですがね…



リンク

2014/2/1(Sat) 10:33:39|NO.59588

前に別PCでrndを使うプログラムを動かした時は、同じ数値だったような・・・
私のPCでは、
41
8467
6334
6500
9169
でした。

repeat 5 mes ""+rnd(10000) loop



ZAP

リンク

2014/2/1(Sat) 10:39:13|NO.59589

kanahironさん

ありがとうございます。

WindowsとAndroidではランタイムのエンジンが異なるでしょうから
変わっても仕方ないのでしょうね。

質問の意図は、Windowsアプリという前提で、OS等の環境が異なる場合
どうなるのだろう、というつもりで質問させていただきました。



ZAP

リンク

2014/2/1(Sat) 10:46:53|NO.59590

空さん

ありがとうございます。

自分も手持ちのいくつかの環境では同じ初期値なら同じ系列の乱数が発生したのですが、

果たして
「いかなる環境で実行しても、初期値が同じなら100%同じ系列で乱数が発生する」
ということを大前提としたプログラムを組んでよいものか、
将来的にOSのバージョンが変わったりしたときにも、この前提は崩れないのか、
そこらへんが知りたかったのです。



MillkeyStars

リンク

2014/2/1(Sat) 11:47:44|NO.59593

マルチプラットフォームで同じ乱数を作るなら、単純に自作した方がいい。
Windows で使える関数・アンドロイドで使える関数が違うから、結果も違う。

xorshift でググるといろいろ出てくるから、それを HSP の計算方式に変えればいいと思う。
計算だけは、どのプラットフォームでも同じ結果だと思う 99.9%。
(昔どっかのイ○テルさんが重大なバグやってるから、100%とは言い切れないのが・・・)



ZAP

リンク

2014/2/1(Sat) 12:04:13|NO.59594

MillkeyStarsさん

ありがとうございます。
自作の疑似乱数ですが、xorshiftについては調べてみます。

自分は、Mersenne Twisterで要素数65536個程度の
整数値の乱数テーブルをあらかじめ作っておいて
プログラム中ではそれを配列に入れて順番に参照し
必要に応じて加工する、といった原始的な方法を考えてました。



donn

リンク

2014/2/1(Sat) 13:15:10|NO.59595

HSP(Windows版)のrndはHSP開発環境であるVisual C++のrand関数をそのまま呼び出してます。
このソースは公開されてますし中身は単純な計算をしているだけです。
なのでOSなどに影響されず結果は常に同じになります。
Visual C++のrandの仕様が将来変わればそうではなくなるかもしれませんがその可能性は低いと思います。
ちなみにrndが具体的にどんな計算をしているかは以下のモジュールを見てください。


//rndと同じ動作をするモジュール #module #deffunc randomize2 int seed holdrand=seed return #defcfunc rnd2 int maxn holdrand = holdrand * 214013 + 2531011 return (holdrand>>16&0x7fff)\maxn #global #uselib "kernel32.dll" #cfunc GetTickCount "GetTickCount" //rndとrnd2が同じ値を返すか実験 randomize randomize2 GetTickCount() repeat 20 r=rnd(32768) r2=rnd2(32768) mes ""+r+","+r2 loop stop



ZAP

リンク

2014/2/1(Sat) 21:03:12|NO.59600

donnさん

解説ありがとうございます。
こんな単純なロジックだったのですね!

これにて解決としたいと思います。



ONION software Copyright 1997-2021(c) All rights reserved.