どのような違いがあるMath.random() * n
とRandom.nextInt(n)
どこn
の整数がありますか?
どのような違いがあるMath.random() * n
とRandom.nextInt(n)
どこn
の整数がありますか?
回答:
以下は、 GiliがリンクしているSunフォーラムの投稿からの「Random.nextInt(n)
より効率的で偏りの少ない理由」の詳細な説明ですMath.random() * n
。
Math.random()は内部的にRandom.nextDouble()を使用します。
Random.nextDouble()はRandom.next()を2回使用して、仮数部にほぼ均一に分散されたビットを持つdoubleを生成するため、0〜1-(2 ^ -53)の範囲で均一に分散されます。
Random.nextInt(n)は、平均して2回未満のRandom.next()を使用します-1回使用します。取得した値がMAX_INT未満のnの最大倍数を超える場合は、再試行します。それ以外の場合は、nを法とする値(これを返します) MAX_INTを下回るnの最大倍数を超える値が分布を歪曲するのを防ぎます)。そのため、0からn-1の範囲で均一に分布する値を返します。
6倍にスケーリングする前は、Math.random()の出力は、一様分布から得られた2 ^ 53の可能な値の1つです。
6によるスケーリングは可能な値の数を変更せず、intにキャストすると、これらの値は6つの「バケット」(0、1、2、3、4、5)のいずれかに強制され、各バケットはいずれかを含む範囲に対応します1501199875790165または1501199875790166(6は2 ^ 53のアドバイザーではないため)これは、十分な数のダイスロール(または十分に多数のサイドを持つダイス)の場合、ダイスが大きなバケットに向かってバイアスされていることを示します。
この効果が現れるまで、非常に長い時間ダイスを振るのを待ちます。
Math.random()も約2倍の処理を必要とし、同期の影響を受けます。
6
で5
に置き換えます。「5バイアス」になります。サイコロに問題があることに気付く前に、サイコロを数回投げることができます。ランダムジェネレーターに問題があることに気付く前に、非常に高度な綿密な調査を行わなければなりません。
https://forums.oracle.com/forums/thread.jspa?messageID=6594485�に よるRandom.nextInt(n)
と、より効率的でバイアスが少ないMath.random() * n
この例によればRandom.nextInt(n)
、Math.random()* nよりも予測可能な出力が少なくなります。[ソートされていない配列よりもソートされた配列の方が速い] [1]によると、Random.nextInt(n)は予測が難しいと言えます。
usingRandomClass:時間:328マイル秒。
usingMathsRandom:時間:187マイル秒。
package javaFuction;
import java.util.Random;
public class RandomFuction
{
static int array[] = new int[9999];
static long sum = 0;
public static void usingMathsRandom() {
for (int i = 0; i < 9999; i++) {
array[i] = (int) (Math.random() * 256);
}
for (int i = 0; i < 9999; i++) {
for (int j = 0; j < 9999; j++) {
if (array[j] >= 128) {
sum += array[j];
}
}
}
}
public static void usingRandomClass() {
Random random = new Random();
for (int i = 0; i < 9999; i++) {
array[i] = random.nextInt(256);
}
for (int i = 0; i < 9999; i++) {
for (int j = 0; j < 9999; j++) {
if (array[j] >= 128) {
sum += array[j];
}
}
}
}
public static void main(String[] args) {
long start = System.currentTimeMillis();
usingRandomClass();
long end = System.currentTimeMillis();
System.out.println("usingRandomClass " + (end - start));
start = System.currentTimeMillis();
usingMathsRandom();
end = System.currentTimeMillis();
System.out.println("usingMathsRandom " + (end - start));
}
}
Math.random()