• ベストアンサー

乱数について(Rnd関数)

すみません。質問があります。 VBAを用いてパチスロシミュレータを作成しているのですが 乱数が偏っている気がしてなりません。 乱数はRnd関数を用いて0~65535の範囲で生成しています。 もちろん初期化時にRandomizeも用いています。 毎ゲーム開始時にそのゲームで必要な乱数を4つ r1 = Int(Rnd() * 65536) r2 = Int(Rnd() * 65536) r3 = Int(Rnd() * 65536) r4 = Int(Rnd() * 65536) というように生成しています。 それらの乱数を用いて複雑なモード移行などを行っているのですが、 ある条件下でr1のあるビットが1になりやすいというような現象が起こります。 乱数に法則性があることは不思議ではないんですが、Rnd関数による乱数っていうのは多少複雑な処理をしただけでこのような不具合が出る可能性があるのでしょうか。 私のプログラムに問題があるとは思うのですが、「もしかして、乱数のせいかも?」という疑念を抱いてデバッグするのはつらいものがあるので。 ですので、 ・変な使い方をすれば目に見えて偏る可能性もある。 という意見の方はその「変な使い方」というのを具体的に教えていただけないでしょうか? また、そのような意見の方がしばらくいらっしゃらない場合はRnd関数による乱数は実用上問題なく使えると解釈したいと思います。 よろしくおねがいします。

質問者が選んだベストアンサー

  • ベストアンサー
  • rinkun
  • ベストアンサー率44% (706/1571)
回答No.2

VBAに限らず言語処理系の標準ライブラリなどで用意している乱数は往々にしてお粗末なものです。 だいたいが線形合同法を使っているので、下位ビットだけ取るなどの使い方をすれば簡単に法則性が出てしまいます。 品質の良い乱数アルゴリズムとしてはメルセンヌ・ツイスタが知られていますが、VBAで使うには重いでしょう。 ゲームの種くらいならRndでもそこそこ使えると思います。 下位ビットだけ使ったり余りに長い系列を使ったりという悪い使い方をしないというのが前提になりますけど。

参考URL:
http://www001.upp.so-net.ne.jp/isaku/rand.html
Ryo0617
質問者

お礼

ありがとうございます。 各乱数の取得時に違う乱数系列を使用すればとりあえずうまくいきました。 r1 = Int(Rnd() * 65536) r2 = Int(Rnd() * 65536) r3 = Int(Rnd() * 65536) r4 = Int(Rnd() * 65536) ↓ r1 = Int(RndUser1() * 65536) r2 = Int(RndUser2() * 65536) r3 = Int(RndUser3() * 65536) r4 = Int(RndUser4() * 65536) モンテカルロ法では乱数がしっかり機能するのかも考慮しなければいけないんですね。 これからも不安です。 お二人ともありがとうございました。

その他の回答 (1)

回答No.1

すみません、あまり読んでませんが。 「VB Rnd function precise」で検索 http://www.15seconds.com/issue/051110.htm 「VB 乱数 精度」でもいけるかも。日本語訳あったし http://japan.internet.com/developer/20060124/26.html 似たような症状を聞いたことがあったので「線形合同式法 カルドセプトサーガ」で検索 http://forzaxbox360.blog56.fc2.com/blog-category-34.html

関連するQ&A

  • 乱数生成について

    VisualBasic2010を使用しています。 コード内に複数回、乱数を生成しています。 普段は始めだけRandomizeして、Rnd関数を使用していて、毎回違う乱数を生成させているのですが、 今回は毎回同じ乱数を生成させたいのですが、どうやったらできるでしょうか? シード値をどうこうするとは、わかったのですがやり方がわかりません。 わかる方、どうぞよろしくお願いします。

  • rnd関数の使い方教えてください。

    初歩的かも知れませんが、よろしお願いします。 仕様環境:Access2007 Win7 ・・・・・ 只今、新規レコードに自動的にランダムな数字が割り振られるように テストしています。 調べたところ「rnd関数」というものを使うということが解りました。 試験用のデータベースを簡単に作り テーブルの項目(フィールド)も簡単にしました。 テストテーブル ------------------- ID(オートナンバー) 名前(テキスト型) 住所(テキスト型) 乱数(テキスト型)または(数値型)←あとで説明しますが。。 ------------------- 乱数のフィールドにある「規定値」にrnd関数を入力しテーブルを保存しようとすると、 「テーブルレベル入力規則の未定義の関数名です。。」と エラーが出てしまいます。テキスト型でも数値型でもです。 rnd関数は、、 int((200-100+1)*rnd+100) ↓入力してエンターを押すと Int((200-100+1)*Rnd()+100)となります。 つまり100から200までの間の数字をランダムに割り振ろうと挑戦しています。 ちなみにテーブルから「乱数」フィールドを消して、フォームにテキストボックスを作り、 コントロールソースに入力しても「未定義です」のようなエラーがでます。(関数の前に”=”もつけたのですが) また規定値に入力しビューで見ると「#Name?」となります。 クエリにrnd関数のフィールドを作ってフォームにつなげても出来ません。 (集計で「演算」にして作ってみたりしたのですが。。) まるっきりrnd関数の使い方がわかりません(汗)。 VBA(モジュール)は使わず、フィールドプロパティなど基本的な機能かマクロでやりたいです。 また重複しないようにしたいのです。 漠然とした相談ですが、どの場面(テーブルやクエリやフォーム)でどう使うか教えてください、 新規レコードにランダムな番号(複数桁で)割り振られるようにしたいです。 宜しくお願いします。

  • Rnd関数って

    VBのRnd関数を使って次のようにフォーム上に値を返させたときに疑問が沸いたのですが。 sub イベント() Dim Data As Single Randomize Data = Rnd() Text1.Text = Data Text2.Text = Int(Data * 100) end sub この何回かイベントを実行すると例えば text1  text2 0.367   36 0.782   78 8.591   8 の様に値が返されてきます。 ここで2つ不思議なのが HELPでRnd関数を調べると、0以上1未満の範囲の値を返します。となっているのに、なぜ8.591の様な値が出てくるのか? さらに8.591を100かけて小数点以下切り捨てると859になるはずが、なぜ8になるのか? 理由がわかる方教えてください。

  • 乱数の発生 Randomizeを入れた方が良いのか

    VBAについて教えてください。 --------------------------- Sub Randomizeを入れた場合() Dim intMax As Integer Dim intMin As Integer Randomize intMin = 1 intMax = 10 Debug.Print Int((intMax - intMin + 1) * Rnd + intMin) End Sub --------------------------- Sub Randomizeを入れていない場合() Dim intMax As Integer Dim intMin As Integer intMin = 1 intMax = 10 Debug.Print Int((intMax - intMin + 1) * Rnd + intMin) End Sub --------------------------- 上記二つのマクロを実行しても 同じような結果が得られる気がするのですがRandomizeは必要なのでしょうか? 一つのサブプロシージャーの中で1回しか乱数を発生させないのなら Randomizeを使って乱数を初期化する必要はないのですか?

  • ACCESSで乱数発生

    宜しくお願いいたします。 ACCESS2000でかるた取りゲームを作成しています。 かるたを任意に配置するために乱数を設定するのに Randomize DoCmd.RunSQL "update 回答 set 整列No.=100*rnd(1) " として、一応乱数が整列No.に張り付いているのですが常に同じ数列になっています。 数列を起動の都度変更するにはどのようにしますか

  • 乱数で同じものが出ない処理ってどうやるんですか?

    .NETでタイピングゲームを作っています。 乱数を使って日本語とそのローマ字を1セットとして表示していくプログラムなんですが、どうしても同じものが出てしまうのですが、同じ日本語とローマ字のセットが表示されないようにするにはどうすればよいでしょうか? ちなみに、コード下記のように作りました。 Randomize() 乱数 = Math.Floor(Rnd() * 要素数) + 1 If 乱数 Mod 2 = 0 Then '乱数が偶数の時 Label1.Text = Typeword(乱数 - 1) '日本語表示 Label2.Text = Typeword(乱数) 'ローマ字表示   elseで、乱数が奇数の処理を行う。

  • VBA AからZで乱数を発生させたい

    Sub AからZで乱数を発生させる() Dim 最大値 As Integer Dim 最小値 As Integer Randomize 最小値 = 1 最大値 = 10 Debug.Print Int((最大値 - 最小値 + 1) * Rnd + 最小値) End Sub --------------------------------------------------------- これを実行すると、1から10の間で乱数を発生させられるのですが、 AからZの間で乱数を発生させたい場合は、 このコードをどのようにすればいいでしょうか? アドバイスよろしくお願いします。

  • こんな条件を満たす乱数生成関数教えてください

    1.任意の周期を指定できる 2.種を指定できる(直前の生成値を引数にとる) 3.逆関数が定義できる 4.生成された乱数 x、y の距離を(定数時間で)求められる   つまり y = f(x) ならxとyの距離は1、 y = f( f( f(x) ) ) なら距離3、というように 乱数としての質(均等に分布していること)はあまり重視しません。 ビット幅は32~128bitくらい(任意ならベスト)であればいいと思っています。 以下のような感じにしたいです。  int rand(x, p);   // 戻り値 y = f(x)、pは周期、xは直前の乱数値  int inv(y, p);   // 戻り値 x = f^-1(y)  int distance(x, y) // y = f(f(x)) のとき、distance(x, y) = 2 で distance(y, x) = -2 一応以下の関数が条件1~4を満たすのですが、残念ながら乱数としての性質が皆無なので使えないです。  int rand(x, p) { return (x+1) % p; }  int inv(y, p) { return y ? y - 1 : p-1; }  int distance(x, y) { return y - x; } よろしくご教授お願いします。

  • 重複なし乱数について

    重複なし乱数について VBAで重複なしの乱数を使ったプログラムを作りたいのですが上手く作れません。 助言お願い致します。 作るのは数比べゲームです。 フォーム上にボタン0~9を配置し、ボタンを押すごとに重複しない乱数をPC側で表示させ、 選択した数字と乱数を比較し勝敗を決定するというゲームです。 エクセル上に重複なし乱数を表示する方法はなんとなく分かるのですが、 ボタンを押すごとに重複なし乱数を取得する処理を行う方法が分かりません。 現状としては ボタンを押した処理の欄に pcNo = Int(9 * rnd + 0) を書いてただ乱数を取得している状態です。 回答よろしくお願い致します。

  • 重複しない乱数整数を発生させる。

    重複しない乱数整数を発生させるため、次のような構文を作りましたが、うまくいきません。 アドバイスをお願いします。 Sub RRR() Dim A, B, C, D, E As Integer A = 1 B = 10 For D = A To B Randomize E = Int((B - A + 1) * Rnd + A) Cells(D, 1) = E Next D End Sub

専門家に質問してみよう