すいません、VB4しかやってないんです、VBAはやったけど(ぼそ) チラシの裏だって立派な書き込み空間なんだからねっ!資源の有効活用なんだからねっ!とか偉そうに言ってるけど、実は色々と書き残したいだけ

だからなに? どうしろと? くるみサイズの脳みそしかないあやしいジャンガリアンベムスターがさすらう贖罪蹂躙(ゴシックペナルティ)

ホーム 連絡をする 同期する ( RSS 2.0 ) Login
投稿数  632  : 記事  35  : コメント  11666  : トラックバック  143

ニュース


片桐 継 は
こんなやつ

かたぎり つぐ ってよむの

大阪生まれ河内育ちなんだけど
関東に住みついちゃったの
和装着付師だったりするの
エセモノカキやってたりするの
VBが得意だったりするの
SQL文が大好きだったりするの
囲碁修行中だったりするの
ボトゲ好きだったりするの
F#かわいいよF#

正体は会った人だけ知ってるの

空気読まなくてごめんなさいなの


わんくまリンク

C#, VB.NET 掲示板
C# VB.NET掲示板

わんくま同盟
わんくま同盟Blog


WindowsでGo言語
WindowsでGo言語


ネット活動


SNSは疲れました

記事カテゴリ

書庫

日記カテゴリ

ギャラリ

イベント活動

プログラムの活動

ランダムな数字を取り出すのには、Randomクラスを使う。

Random (Java Platform SE 6)
http://docs.oracle.com/javase/6/docs/api/java/util/Random.html

たとえば、サイコロのアプリケーションを考えた時、1~6の整数の間でランダムな数字を取り出したい、ってことがあると思う。

ふと思ったのだけれど、その時にRandomクラスをどう使えば、できるだけ結果が平等になるんだろうか。

500回振ったとして、アプリケーションの作り方は次の考え方があると思う。

  • 一回だけNewして、ランダム値を500回取る。
  • 500回Newして、ランダム値を取る。

インスタンスの生成と破棄を考えたら、まぁ前者で作るんだけど、それでいいのかしらん?

と考え込んでしまったので、サンプルアプリを書いてみた。

   1:  /**
   2:   * サイコロサンプルアプリ
   3:   * @author esten
   4:   *
   5:   */
   6:  public class RandomTests {
   7:      // 6面ダイスを count 回振ってみる
   8:      static int dice = 6;
   9:      static int count = 500;
  10:      /**
  11:       * 結果を画面に表示する
  12:       * @param rolled
  13:       */
  14:      private static void print(int[] rolled){
  15:          final String formatString = "dice %d = (%4d) %s \n";
  16:          DecimalFormat df = new DecimalFormat("#0.00%");
  17:          for (int i = 0 ; i < dice ; i++){
  18:              System.out.printf(formatString, i, rolled[i], df.format((double) rolled[i] / count));
  19:          }
  20:      }
  21:      /**
  22:       * @param args
  23:       */
  24:      public static void main(String[] args) {
  25:          int[] rolled = new int[dice];
  26:          // ランダム一回パターン
  27:          Random rnd = new Random();
  28:          for (int i = 0 ; i < count ; i++){
  29:              rolled[rnd.nextInt(dice)] += 1;
  30:          }
  31:          System.out.println("One New");
  32:          print(rolled);
  33:          System.out.println("---");
  34:          // ランダムnewパターン
  35:          rolled = new int[dice];
  36:          for (int i = 0 ; i < count ; i++){
  37:              rnd = new Random();
  38:              rolled[rnd.nextInt(dice)] += 1;
  39:          }
  40:          System.out.println("New in loop");
  41:          print(rolled);
  42:          System.out.println("---");
  43:      }
  44:  }

で、実行してみた結果。まぁ、何回かやってみるわけだけど。

One New
dice 0 = (  86) 17.20% 
dice 1 = (  86) 17.20% 
dice 2 = (  84) 16.80% 
dice 3 = (  83) 16.60% 
dice 4 = (  84) 16.80% 
dice 5 = (  77) 15.40% 
---
New in loop
dice 0 = (  77) 15.40% 
dice 1 = (  70) 14.00% 
dice 2 = (  91) 18.20% 
dice 3 = (  93) 18.60% 
dice 4 = (  88) 17.60% 
dice 5 = (  81) 16.20% 
---

うーん、差は大きなものではない感じ。どっちでもいいのかな? サンプル回数を増やしてみよう。count = 50000で^^;

One New
dice 0 = (8380) 16.76% 
dice 1 = (8444) 16.89% 
dice 2 = (8222) 16.44% 
dice 3 = (8287) 16.57% 
dice 4 = (8282) 16.56% 
dice 5 = (8385) 16.77% 
---
New in loop
dice 0 = (8304) 16.61% 
dice 1 = (8309) 16.62% 
dice 2 = (8402) 16.80% 
dice 3 = (8391) 16.78% 
dice 4 = (8259) 16.52% 
dice 5 = (8335) 16.67% 
---

あんまり差が出ない。でも、処理時間が後者だと目に見えて遅いのが判った。ってことは、前者の方法で良さげ。納得して使おう。

投稿日時 : 2014年7月29日 22:03

コメント

# re: Javaを使っている時に、狭範囲内でランダムな整数をできるだけ平等に取りたい。 2014/07/31 17:59 aetos
一般に疑似乱数は、シード値を元に乱数を生成します。
で、
・最初は時刻などの値をシードにする
・2 回目以降は前回の値をシードにする
という処理をします。

なので、同一の Random のインスタンスで 2 回続けて生成した数は必ず違うものになります。
が、Random をいくつも生成すると、万が一、複数の Random のインスタンスで同一のシード値になってしまった場合、次に生成される乱数は同じ値になってしまいます。
シード値を明示的に与えるコンストラクタを使って 2 つの Random インスタンスを作ると、全く同じ数列を生成するはずです。

まぁ、普通、既定のシード値がマイクロ秒とかまで同一にはならないと思いますが。
特段の理由がない限り、一つのインスタンスを使い回すのが普通です。

Post Feedback

タイトル
名前
Url:
コメント