質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

5回答

4861閲覧

java Random()で整数60000までのランダムの数値を完全性で出力するにはどうすればよいですか

King_of_Flies

総合スコア382

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2017/11/21 05:41

http://ysklog.net/java/4-15.html

上記の参考サイトの
「0~3の整数」を生成するには、「0~4未満の実数」を以下のように作成し、
Math.random()*4;
これをint型にキャストすればよい。
(int)(Math.random()*4);

という個所を見て思ったのですが、
これはMath.Random()で0.0<1.0のランダムな数値をとって、
こいつを4倍し、少数点以下を切り捨てるという処理だと思うのですが、

桁が上がった場合、単純に
Math.radom()*60000;
これをint型にキャストすればよい。
(int)(Math.random()*60000)ってことになるわけもないですよね。

「060000の整数」を生成するための、「060000未満の実数」を作成したい場合どうすればよいでしょうか。

お願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答5

0

出来る限り品質のよい乱数を得るには、java.util.Randomを使うことはおすすめしません。
http://koiroha.blogspot.jp/2017/05/java-random-deviation-probrem.html
SecureRandomというクラスもありますが、これは生成される乱数の品質が良い代わりに超遅いです。

ゲーム製作などの現場では、出来る限り品質の高い、かつ計算速度が速い、かつ同シード値から同一の乱数配列が取れる乱数生成方法としてメルセンヌ・ツイスタがよく挙げられます。しかし、Javaの標準機能にメルセンヌ・ツイスタを使ったクラスは存在しないため、なんらかの外部ライブラリを使うか、自分でメルセンヌ・ツイスタを使った乱数生成コードを実装する必要があります。

【乱数の偏りについての参考記事】
https://qiita.com/isonami/items/1cc278cbf2093d2d6abd

【メルセンヌ・ツイスタのJava実装の一例】
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/VERSIONS/JAVA/java.html
※ソースコードは中ほどのMTRandom.javaというリンク

投稿2017/11/21 06:10

編集2017/11/21 06:18
masaya_ohashi

総合スコア9206

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2017/11/21 06:18 編集

C言語のrand()ほどではないにしても、「互換上1度実装したアルゴリズムを変えられない」結果残念なことになっているケースは多いですね… PHPのmt_randも、間違ったままの実装をPHP7.1でも選べるようになっている、とのことですし。 http://php.net/manual/ja/function.mt-srand.php
guest

0

java.util.Random#nextInt(int)

この乱数ジェネレータのシーケンスを使って、0から指定された値の範囲(0は含むが、その指定された値は含まない)で一様分布のint型の擬似乱数値を返します。nextIntの一般規約では、指定された範囲内の1つのint型の値が擬似乱数として生成されて返されます。bound個のすべての可能なint値が(ほぼ)均等な確率で生成されます。nextInt(int bound)メソッドは、Randomクラスによって次のように実装されます。

かしら?

投稿2017/11/21 05:53

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

(int)(Math.random()*60000)

アバウトにはこれでも構いません(浮動小数点数の取りうる値の関係上、完全に均等とはなりませんが)。ただ、本格的に使いたいなら、java.util.Random()インスタンスを用意した方がいいでしょう。

java

1Random source = new Random(); 2int randomInt = source.nextInt(60000);

実数の場合、何をもって「均等」というかが難しくなってきます(浮動小数点数という都合上、とりうる値の間隔は大きな数ほど隙間が空いてきます)。アバウトでいいならMath.random()*60000で構いません。

投稿2017/11/21 05:51

maisumakun

総合スコア145184

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KSwordOfHaste

2017/11/21 06:13 編集

計算機の乱数計算の一様性という意味ですと十分満足いくように一様にするのが難しいという話はあると思いますが、maisumakunさんがおっしゃっている以下の点については問題はないと思います。(ほぼという意味合いで) > 浮動小数点数という都合上、とりうる値の間隔は大きな数ほど隙間が空いてきます というのはrandom()の実装は53bitの整数を生成し、それを0.0~1.0になるようにスケーリングしているからです。この実装においては2進数としての末尾の誤差はありますが生成される数値は可能な限り一様になっているといえるのではないでしょうか?
KSwordOfHaste

2017/11/21 06:07

あ・・・でもnextInt(60000)の方が適切という意見には同意です!
guest

0

ベストアンサー

Random#nextIntでは要件に合わないでしょうか。

https://docs.oracle.com/javase/jp/8/docs/api/java/util/Random.html#nextInt-int-


追記:

masaya_ohashiさんのご回答の通り、乱数生成には色々な考慮が必要です。
リンク頂いているJava 標準 Random の乱数偏り問題の記事にも記載がありますが、
Random#nextIntは、おおよそ一様に分布します。
また、メルセンヌ・ツイスタ以外の疑似乱数生成アルゴリズムとしては、例えばXorshift等も有名かと思います。

投稿2017/11/21 05:50

編集2017/11/21 07:20
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

King_of_Flies

2017/11/21 07:22

nextIntの使い勝手がよさそうなので、一番最初に回答してくださった方にBAを差し上げることにしました。 ありがとうございます。
guest

0

(int)(Math.random()*60000)ってことになるわけもないですよね。

ってことになると思いますが、なぜならないと思うのでしょうか?

投稿2017/11/21 05:52

fuzzball

総合スコア16731

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

King_of_Flies

2017/11/21 06:05 編集

Math.random()で取得できる値は0~1未満の実数ということなので、 0,0.1,0.2,0.3,0.4,…0.9までを取得しますよね。 0.1に60000を掛けてint型にキャストしても6000が返ってきませんか?
maisumakun

2017/11/21 06:13

> 0,0.1,0.2,0.3,0.4,…0.9までを取得しますよね。 「0.5576118308783207」とか「0.9369795477265435」とか、下の位までランダムです。
fuzzball

2017/11/21 06:17 編集

@King_of_Flies さん 返ってきますけど、それが何か? 「0以上1未満の実数」 * 60000 = 「0以上60000未満の実数」で、これをintでキャスト(切り捨て)すると「0以上59999以下」のint(整数)になります。
King_of_Flies

2017/11/21 07:19 編集

@fuzzball >返ってきますけど、それが何か? 0のとき0, 0.1のとき6000, 0.2のとき12000, 0.3のとき18000, //略 0.9のとき、54000となると、 1とか2とか取得できなくないですか?という事を疑問に思ったのですが、 上のmaisumakunさんの回答で実数の勘違いをしていたことに気付いたので解決しました。 あと、言い方がキツくて怖いです。
fuzzball

2017/11/21 07:25

怖くないですよw
King_of_Flies

2017/11/21 07:46

攻め立てる意図がなくてよかったです。 >返ってきますけど、それが何か? (なんでそんなことも分かんないのこのカスは)くらいの意味を感じました・・・
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問