Sự khác biệt giữa Math.random() * n
và Random.nextInt(n)
đâu n
là một số nguyên?
Sự khác biệt giữa Math.random() * n
và Random.nextInt(n)
đâu n
là một số nguyên?
Câu trả lời:
Dưới đây là lời giải thích chi tiết về lý do tại sao " Random.nextInt(n)
cả hiệu quả hơn và ít sai lệch hơn Math.random() * n
" từ bài đăng trên diễn đàn Mặt trời mà Gili liên kết đến:
Math.random () sử dụng Random.nextDouble () trong nội bộ.
Random.nextDouble () sử dụng Random.next () hai lần để tạo ra một nhân đôi có các bit được phân phối đồng đều trong lớp phủ của nó, do đó, nó được phân phối đồng đều trong phạm vi 0 đến 1- (2 ^ -53).
Random.nextInt (n) sử dụng Random.next () trung bình ít hơn hai lần - nó sử dụng một lần và nếu giá trị thu được cao hơn bội số cao nhất của n dưới MAX_INT, thì nó sẽ trả về giá trị modulo n (điều này ngăn các giá trị trên bội số cao nhất của n dưới MAX_INT làm lệch phân phối), do đó trả về một giá trị được phân phối đồng đều trong phạm vi 0 đến n-1.
Trước khi chia tỷ lệ 6, đầu ra của Math.random () là một trong 2 ^ 53 giá trị có thể được rút ra từ phân phối đồng đều.
Chia tỷ lệ theo 6 không làm thay đổi số lượng giá trị có thể và chuyển sang int sau đó buộc các giá trị này vào một trong sáu 'nhóm' (0, 1, 2, 3, 4, 5), mỗi nhóm tương ứng với các phạm vi bao gồm một trong hai 1501199875790165 hoặc 1501199875790166 của các giá trị có thể (vì 6 không phải là giá trị của 2 ^ 53). Điều này có nghĩa là đối với một số lượng xúc xắc đủ (hoặc một con súc sắc có số lượng cạnh đủ lớn), con súc sắc sẽ tự cho thấy mình bị lệch về phía các thùng lớn hơn.
Bạn sẽ chờ đợi một con xúc xắc lăn rất lâu để hiệu ứng này xuất hiện.
Math.random () cũng yêu cầu xử lý gấp đôi và có thể đồng bộ hóa.
6
bằng 5
trên một khối súc sắc: nó sẽ là "5-bias". Bạn có thể ném xúc xắc một vài lần trước khi bạn nhận thấy có gì đó không ổn với xúc xắc. Bạn buộc phải thực hiện một kiểm tra kỹ lưỡng cực kỳ tinh vi trước khi bạn nhận thấy có gì đó không ổn với một trình tạo ngẫu nhiên.
Theo https://forums.oracle.com/forums/thread.jspa?messageID=6594485龵 Random.nextInt(n)
vừa hiệu quả hơn và ít sai lệch hơnMath.random() * n
Theo ví dụ Random.nextInt(n)
này có đầu ra ít dự đoán hơn thì Math.random () * n. Theo [mảng được sắp xếp nhanh hơn một mảng chưa sắp xếp] [1] Tôi nghĩ rằng chúng ta có thể nói Random.nextInt (n) là khó dự đoán .
usingRandomClass: Thời gian: 328 milesecond.
usingMathsRandom: Thời gian: 187 milesecond.
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()