JS tạo boolean ngẫu nhiên


134

Câu hỏi đơn giản, nhưng tôi quan tâm đến các sắc thái ở đây.

Tôi đang tạo booleans ngẫu nhiên bằng phương pháp sau Tôi tự nghĩ ra:

const rand = Boolean(Math.round(Math.random()));

Bất cứ khi nào random()xuất hiện, dường như luôn có một cạm bẫy - nó không thực sự ngẫu nhiên, nó bị xâm phạm bởi thứ này hay thứ khác, v.v. Vì vậy, tôi muốn biết:

a) Cách trên có phải là cách thực hành tốt nhất không?

b) Tôi có suy nghĩ quá nhiều không?

c) Tôi có suy nghĩ quá mức không?

d) Có cách nào tốt hơn / nhanh hơn / thanh lịch hơn tôi không biết?

(Cũng có phần thích thú nếu B và C loại trừ lẫn nhau.)

Cập nhật

Nếu nó tạo ra sự khác biệt, tôi đang sử dụng điều này để di chuyển một nhân vật AI.


25
const rand = Math.random() < 0.5là tương đương và đơn giản hơn.
Hamms

3
Bạn chỉ có thể đạt được giả danh , không thực sự ngẫu nhiên.
Oriol

Không có gì là thực sự ngẫu nhiên, mục tiêu là càng gần với ngẫu nhiên càng tốt.
Adam Hội trưởng Smith

Và nếu bạn có cơ hội 50/50, math.randomnên có rất nhiều. Chỉ cần sử dụng mili giây cho hạt giống của bạn.
Adam Hội trưởng Smith

Tôi nghĩ rằng nó khá ngẫu nhiên khi một người truy cập một trang web: D vì vậy tôi đã có ý tưởng này ...Boolean(+Date.now()%2)
Roko C. Buljan

Câu trả lời:


337

Về mặt kỹ thuật, mã trông ổn, nhưng hơi phức tạp một chút. Bạn có thể so sánh Math.random()để 0.5trực tiếp, như phạm vi Math.random()[0, 1)(điều này có nghĩa là 'trong khoảng 0-1 bao gồm 0, nhưng không phải 1'). Bạn có thể chia phạm vi thành [0, 0.5)[0.5, 1).

var random_boolean = Math.random() >= 0.5;

// Example
console.log(Math.random() >= 0.1) // %90 probability of get "true"
console.log(Math.random() >= 0.4) // %60 probability of get "true"
console.log(Math.random() >= 0.5) // %50 probability of get "true"
console.log(Math.random() >= 0.8) // %20 probability of get "true"
console.log(Math.random() >= 0.9) // %10 probability of get "true"


3
Tôi thích một giải pháp này, vì nó cho phép bạn điều chỉnh xác suất đúng / sai
Đồng hành

nếu bạn thay đổi số 0,5 thành 0,9 chẳng hạn, điều này có làm tăng xác suất sai không, và bằng cách nào?
Đặc vụ Zebra

nếu bạn thay đổi từ 0,5 đến 0,9. Sau đó, xác suất có khả năng được thay đổi. Tôi nghĩ bạn có thể thử nó với một số lượng lớn vòng lặp ngẫu nhiên, như 10000 lần lặp.
Kelvin

Đối với JavaScript hiện đại, bạn nên sử dụng lettức làlet randomBool = Math.random() >= 0.5;
Chris Halcrow


13

Để có giá trị bảo mật hơn về mật mã, bạn có thể sử dụng crypto.getRandomValuestrong các trình duyệt hiện đại.

Mẫu vật:

var randomBool = (function() {
  var a = new Uint8Array(1);
  return function() {
    crypto.getRandomValues(a);
    return a[0] > 127;
  };
})();

var trues = 0;
var falses = 0;
for (var i = 0; i < 255; i++) {
  if (randomBool()) {
    trues++;
  }
  else {
    falses++;
  }
}
document.body.innerText = 'true: ' + trues + ', false: ' + falses;

Lưu ý rằng cryptođối tượng là API DOM, vì vậy nó không có sẵn trong Node, nhưng có một API tương tự cho Node .


4
Math.random()nổi tiếng là không ngẫu nhiên theo nhiều cách, gợi ý thay thế tuyệt vời
Charles Harris

3
Tôi sẽ thêm một hiệu chỉnh nhỏ ở đây, vì tôi đã phát hiện ra sau 50 000 000 lượt chạy mà nó tạo ra trung bình 0,78% hoặc nhiều hơn số 0: trả về [0] <= 127; (Không bao gồm 127)
Amund Midtskog

2
@AmundUntskog Gọi tốt. Tôi nên gõ:a[0] > 127
Alexander O'Mara

1
Nhân tiện, bạn thường có thể muốn tạo ra số lượng mẫu lớn hơn nhiều so với chỉ 255. Thay vào đó, để giảm tiếng ồn trong dữ liệu, đại loại như 100.000 - hoặc thậm chí hàng chục triệu, như được đề xuất trong bình luận khác, nếu bạn muốn thấy các lỗi nhỏ đến 0,78%.
caw

8
!Math.round(Math.random());

­­­­­­­­­­­­­­


6
Vui lòng định dạng này hữu ích hơn ( stackoverflow.com/editing-help ) và thêm một số giải thích. Câu trả lời chỉ có mã không được đánh giá cao. Thêm một lời giải thích sẽ giúp chống lại quan niệm sai lầm rằng StackOverflow là một dịch vụ viết mã miễn phí.
Yunnosch

5

Ấn tượng rất nhiều bởi câu trả lời của Kelvin Tôi muốn đề xuất một giải pháp khá tương tự nhưng được tăng cường một chút.

var randomBoolean = Math.random() < 0.5;

Giải pháp này rõ ràng hơn một chút để đọc, bởi vì con số ở phía bên tay phải <cho bạn biết xác suất nhận được truehơn là nhận false, điều này là tự nhiên hơn để hiểu. Cũng <là một biểu tượng ngắn hơn >=;


0

Cái này thì sao?

return Math.round((Math.random() * 1) + 0) === 0;

1
OP tuyên bố rằng ông đã sử dụng các phương pháp tương tự, không cần phải đăng bài này.
Jacob Gunther

-1

Câu trả lời của Alexander O'Mara

chỉ cần thêm đoạn mã nút

const crypto = require('crypto');
const randomBool = (function () {
    let a = new Uint8Array(1);
    return function () {
        crypto.randomFillSync(a);
        return a[0] > 127;
    };
})();

let trues = 0;
let falses = 0;
for (let i = 0; i < 100; i++) {
    if (randomBool()) {
        trues++;
    }
    else {
        falses++;
    }
}

console.log('true: ' + trues + ', false: ' + falses);

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.