投稿
れい rei-nntnd
プチコン3号用ファイル転送プログラムPetitModem Ver.1.2.0公開。 1200bpsまでのPC-プチコン間の双方向転送が可能。 KEY:433DX43 PC用:http://rei.to/petitmodem.html
19そうだね
プレイ済み
返信[1]
親投稿
AGO tm0506
公開キー、433DX43ではなく4333DX43じゃないですか?
0そうだね
プレイ済み
返信[2]
親投稿
れい rei-nntnd
そうだった… なんか自分の公開キー、3ばっかりなの
0そうだね
プレイ済み
返信[3]
親投稿
こうやま kouyama1967
>なんか自分の公開キー、3ばっかりなの  乱数のかけ方などに偏りがあり同じ文字が連続する事が、非常によくあるようです。私もです。これ以上はセキュリティにからみそうなので略w
0そうだね
プレイ済み
返信[4]
親投稿
れい rei-nntnd
そういやプチコンの乱数はなにつかってんだろうなぁ メルセンヌツイスタってことはないだろうし
1そうだね
プレイ済み
返信[5]
親投稿
ツララ LongIceSword
3号のRND()はシードIDが指定出来るみたいですけど、あれってどんな使い方するんでしょうかね。
0そうだね
プレイ済み
返信[6]
親投稿
れい rei-nntnd
同じ乱数列を生成したいときでしょ シミュレーションとかだと必須 そういやプチコンの乱数生成の速度はかってないや 遅かったらXorShiftでも組んでみるかな
0そうだね
プレイ済み
返信[7]
親投稿
おちゃめ ochame_nako
 プチコンのRND関数は初代およびmkIIでは私の検証では線形合同法に手を加えたものだと感じました。やはり、速度面では線形合同法はかなり有利ですからね。  私がmkIIで作った速度と短さ重視の自作疑似乱数ルーチンも線形合同法の改良版を使っていて1画面プログラムなどで実際に活用しています。mkIIまでは乱数列を指定できなかったので同じ乱数列の乱数を発生させることで面データの自動生成を行っています。
0そうだね
プレイ済み
返信[8]
親投稿
おちゃめ ochame_nako
ちなみにmkIIではたったこれだけで周期1800万以上の疑似乱数を発生できます。 Y=(Y+0.1)%1.1X=(X*117+Y)%1 プチコン3号ではシードIDの設定が可能になったので不要になってしまいましたが。
0そうだね
プレイ済み
返信[9]
親投稿
れい rei-nntnd
あー… その乱数生成器は残念ながらダメなんです… 線形合同法(以下LCG)で周期を伸ばすのには、縦につなげてしまうと周期は二つの掛け算にはならず、もっともっと小さくなってしまいます。 やってみればわかりますが、それだとよくて200~400万、種によっては数万になってしまうかと。 また、あまりよくないモアレ的なものが出てしまいます。 LCGを組み合わせて周期を伸ばすには、並列でつなぐ方法を用います。 Y=(Y+0.1)%1 X=(X+0.2)%0.99 R=(X-Y)%(0.9997) if R=0 then R=0.9997 こんな感じで。(固定小数点の計算は適当w これをCombined Linear Congruential Generator(CLCG)と言います。 ほぼ同じ計算量で周期はきちんと二つのLCGの掛け算になり、怪しいモアレも出にくくなります。
0そうだね
プレイ済み
返信[10]
親投稿
おちゃめ ochame_nako
残念ながらその値だとランダム性は極めて低い粗悪な疑似乱数になっています。 私が作ったものは固定小数点の特性を活かしモアレが少なくシードがどんな値であっても周期は1800万以上を保証されていて線形合同法の割にはランダム性が高くなっています。 線形合同法の場合は周期が長くてもランダム性が低いものになりがちですが私が作ったものはプチコンの標準RND関数レベルは確保されています。 これは実際にプロットしてみれば一目瞭然です。(下記は256x256のサイズにプロットするmkII用プログラム) 私が作った方はリストの長さは半分以下で速度は約2倍(乱数発生部分のみの比較)という優れものというのが分かるでしょう。
0そうだね
プレイ済み
返信[11]
親投稿
おちゃめ ochame_nako
私の疑似乱数 ACLS PNLTYPE "OFF" X=0:Y=0  FOR I=0 TO 9999   FOR J=0 TO 9999    GOSUB @RND:A=X*256:GOSUB @RND:B=X*256    GPAGE 0:GPSET A,B,15:GPAGE 1:GPSET A,B-192,15   NEXT  NEXT END @RND Y=(Y+0.1)%1.1X=(X*117+Y)%1:RETURN
0そうだね
プレイ済み
返信[12]
親投稿
おちゃめ ochame_nako
れいさんの疑似乱数(※X-Yが負数の場合が考慮されてないのでABSを付けました) ACLS PNLTYPE "OFF" X=0:Y=0  FOR I=0 TO 9999   FOR J=0 TO 9999    GOSUB @RND:A=R*256:GOSUB @RND:B=R*256    GPAGE 0:GPSET A,B,15:GPAGE 1:GPSET A,B-192,15   NEXT  NEXT END 下記に続く
0そうだね
プレイ済み
返信[13]
親投稿
おちゃめ ochame_nako
上記の続き @RND Y=(Y+0.1)%1 X=(X+0.2)%0.99 R=ABS(X-Y)%(0.9997) IF R==0 THEN R=0.9997 RETURN
0そうだね
プレイ済み
返信[14]
親投稿
れい rei-nntnd
うーん… 何処で見つけたのか、どう計算したのかわかりませんが、残念ながらそれだとアルゴリズムがダメなので最大周期が保証されてないんですよ 証明は…余白が足りないから省略。 X=0:Y=0 FOR I=0 TO 2000:FOR J=0 TO 9999 GOSUB @RND IF X==0 AND Y==0 THEN GOTO @AAA NEXT:NEXT @AAA PRINT STR$(I)+RIGHT$("000"+STR$(J),4) こんな感じで試してみてくださいな 初期値が0,0なら4613119回で抜けてしまいます
0そうだね
プレイ済み
返信[15]
親投稿
れい rei-nntnd
プチコンmkIIは持ってないので 固定小数点やmoduloの仕様がわかりませんが、 @RND Y=(Y+0.1)%1.1 X=(X*117+0.2)%1 R=(X-Y+0.9998)%0.9998 IF R==0 THEN R=0.9998 RETURN こんな感じのを代わりにいれてみてください。 きちんと4096*4505≒1800万回の周期が出ます。
0そうだね
プレイ済み
返信[16]
親投稿
おちゃめ ochame_nako
説明しても分かりにくいのでプチコンmkIIで実際に試してみるのが一番だと思います。 私の数値は私のアルゴリズム+mkIIの固定小数点に特化したものなので似たような数値に変更しても全く意味がないです。
0そうだね
プレイ済み
返信[17]
親投稿
れい rei-nntnd
いやだから… そのアルゴリズム、数値だと460万回の周期になってますよと。 1800万回の保証はありません。 ぜひ実際に試してみてくださいな。
0そうだね
プレイ済み
返信[18]
親投稿
ツララ LongIceSword
横槍失礼 >おちゃめさん 3号の倍精度実数をmk2仕様の固定小数点化する関数を作って再現してみたらいいんじゃないでしょうか。 れいさんはmk2持ってないみたいですし。
0そうだね
プレイ済み
返信[19]
親投稿
れい rei-nntnd
たぶん大丈夫ですよ。 409を4096で割ると0.099853515625 410は0.10009765625 なので0.1をmkIIの固定小数点で表すと409 同様に1.1は4505 なのでおちゃめさんのアルゴリズムは整数化すると Yn+1=(Yn+409) mod 4505 Xn+1=(Xn*117 + Yn) mod 4096 で、あってますよね。 この変形LCGの周期が問題で、 恐らくLCG二つだからそれぞれの周期4505と4096をかけて18452480の周期があるはずという主張なんだと思うけど、 実際に計算すると4613120。 YをXのmoduloのなかに入れちゃってるから周期が消えちゃう。 今回は1/4になっちゃってる。
0そうだね
プレイ済み
返信[20]
親投稿
おちゃめ ochame_nako
れいさんの検証プログラムで試したら4613120回でした。 これは線形合同法(LCG)を元に私が考えたオリジナルのアルゴリズムであるためシードに依存しない乱数かを調べるためX、Yの組み合わせが何通りあるかを実機で確かめたのですが、その検証プログラムにバグがあったのかもしれません。 ちなみにリスト短縮前のプログラム(0~4095の乱数を発生)Y=(Y+1)%4095X=(X*117+Y)%4096で試してみるときっちり理論値通りの16773120という周期になりました。(つまりリスト短縮の際に数値を変えたら周期が短くなった) mkIIは乗除算や剰余よりも代入が遅いためCLCGは重いので私の考えたLCG改良版は通常のLCG並の軽さで数値さえ間違わなければCLCGに匹敵する周期を確保できるというのは分かってもらえたのではないかと思います。
0そうだね
プレイ済み
返信[21]
親投稿
おちゃめ ochame_nako
個人的にはLCGの問題点は周期の短さよりも乱数の質(ランダム性)にあると思っています。 それは単純に計算で求めるのが困難なので実機で試してみるのが一番分かりやすいです。 固定小数点は整数を4096で割ったものなのでプチコン3号でmkII用プログラムの移植は簡単にできると思いますが剰余の仕様がmkIIと3号では違うためそこは自作するか整数のみで計算しないといけないですね。
0そうだね
プレイ済み
返信[22]
親投稿
れい rei-nntnd
それでもダメなんです… 確かに4096と1しか離れていない4095を使えば「互に素」ですから周期は伸びるんですが… 今度は近すぎて乱数じゃなくなっちゃう。 こちらを動かしてみてください。(たぶんmkIIで動く) X=0:Y=0:DIM C[16] FOR I=0 TO 10000 GOSUB @RND:X1=(X AND 3):GOSUB @RND:X1=(X AND 3) J=X1+X2*4:C(J)=C(J)+1 NEXT FOR I=0 TO 15 PRINT STR$(C(I))+"/"; NEXT END @RND Y=(Y+1)%4095:X=(X*117+Y)%4096 RETURN
0そうだね
プレイ済み
返信[23]
親投稿
れい rei-nntnd
結果はコレ。 1476/0/0/1023/0/0/1024/1477/0/1023/1477/0/1024/1477/0/0/ 2つのLCGの周期が近すぎて、2回連続で乱数を作ると明確な関連が出てきてしまうんです。 もうそれは乱数じゃありません。 2つのLCGを使って周期を伸ばしたければ、 2つのLCGを独立に動かしたうえで、最後に合成しなければダメなんです。
0そうだね
プレイ済み
返信[24]
親投稿
れい rei-nntnd
あ、説明たりないかな どういうことをやってるかというと、連続で2つ乱数作ったとき、それぞれの下位2ビットがどんな頻度で出現するかを見ているんです。 本当の乱数なら、C(0)~C(15)まで同じような値が入らないといけない。 でも、1000以上現れるパターンと一回も現れないパターンの2種しかない。 これは連続でとった2回の乱数が非常に強く相関していることと、 周波数分布が偏ってることを意味します。 実際によくあるのが画面にランダムに敵を配置するとき。 XYの2回連続で乱数を呼んで敵を配置するのに、何個敵を配置しても「重なっちゃう」ことになる。 なので乱数としてはダメってことなんです。
0そうだね
プレイ済み
返信[25]
親投稿
おちゃめ ochame_nako
線型合同法は下位bitはランダム性が低くなるので上位bitを優先して使用しましょう。これは私のプチコン講座で書いているのでよかったら参考にしてみてください。
0そうだね
プレイ済み
返信[26]
親投稿
れい rei-nntnd
4096周期のLCGより悪くなってしまってますので、 周期を伸ばすために2つをつなげるのであれば独立させるべきだと思いますよ。
0そうだね
プレイ済み
返信[27]
親投稿
おちゃめ ochame_nako
上記のプロットプログラムを実行すれば分かりますが私の考案した方法は上位bitから使えば線型合同法の割には極めて優秀でしかも短く超高速です。mkII用ですがプチコン3号への移植も簡単です。 周期を伸ばしても乱数の質が上がる訳ではありません。
0そうだね
プレイ済み
返信[28]
親投稿
nokubi nokubi
運営者により削除されました。 コメントのID : 3DB-NBL7-BXM-ZM8U-U2L-LB9E