JS menghasilkan boolean acak


134

Pertanyaan sederhana, tapi saya tertarik dengan nuansa di sini.

Saya membuat boolean acak menggunakan metode berikut yang saya buat sendiri:

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

Setiap kali random()muncul, sepertinya selalu ada jebakan - itu tidak benar-benar acak, itu dikompromikan oleh sesuatu atau lainnya, dll. Jadi, saya ingin tahu:

a) Apakah cara terbaik praktik di atas untuk melakukannya?

b) Apakah saya terlalu banyak berpikir?

c) Apakah saya memikirkan hal-hal?

d) Apakah ada cara yang lebih baik / lebih cepat / lebih elegan yang tidak saya ketahui?

(Juga agak tertarik jika B dan C saling eksklusif.)

Memperbarui

Jika itu membuat perbedaan, saya menggunakan ini untuk pergerakan karakter AI.


25
const rand = Math.random() < 0.5setara dan lebih sederhana.
— Hamms

3
Anda hanya dapat mencapai pseudorandomness , bukan benar-benar keacakan.
— Oriol

Tidak ada yang benar-benar acak, tujuannya adalah untuk sedekat mungkin dengan acak.
— Adam Buchanan Smith

Dan jika Anda memiliki peluang 50/50, math.randomharus banyak. Cukup gunakan milidetik untuk benih Anda.
— Adam Buchanan Smith

Saya pikir itu cukup acak ketika seseorang mengunjungi sebuah situs web: D jadi saya punya ide ini ...Boolean(+Date.now()%2)
— Roko C. Buljan

Jawaban:


337

Secara teknis, kodenya terlihat bagus, tapi agak terlalu rumit. Anda dapat membandingkan Math.random()untuk 0.5langsung, sebagai kisaran Math.random()yaitu [0, 1)(berarti ini 'di kisaran 0 ke 1 termasuk 0, tapi tidak 1'). Anda dapat membagi rentang menjadi [0, 0.5)dan [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
Saya suka solusi yang satu ini, karena memungkinkan Anda mengubah kemungkinan benar / salah
— Evanion

jika Anda mengubah angka 0,5 menjadi 0,9 misalnya, apakah ini meningkatkan kemungkinan salah, dan bagaimana?
— Agen Zebra

jika Anda mengubahnya dari 0,5 menjadi 0,9. Kemudian, kemungkinan itu kemungkinan akan berubah. Saya pikir Anda dapat mencobanya dengan sejumlah besar loop acak, seperti 10.000 iterasi.
— Kelvin

Untuk JavaScript modern, Anda harus menggunakan letyaitulet randomBool = Math.random() >= 0.5;
— Chris Halcrow


13

Untuk nilai yang lebih aman secara kriptografis, Anda dapat menggunakannya crypto.getRandomValuesdi peramban modern.

Sampel:

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;

Perhatikan bahwa cryptoobjek adalah DOM API, jadi tidak tersedia di Node, tetapi ada API yang serupa untuk Node .


4
Math.random()sangat tidak acak dalam banyak hal, saran alternatif yang bagus
— Charles Harris

3
Saya hanya akan menambahkan koreksi kecil di sini, karena saya menemukan setelah 50.000 berjalan yang dihasilkan rata-rata 0,78% atau lebih banyak nol: mengembalikan [0] <= 127; (Lain 127 tidak pernah termasuk)
— Amund Midtskog

2
@AmundMidtskog Panggilan bagus. Saya harus mengetik:a[0] > 127
— Alexander O'Mara

1
Ngomong-ngomong, Anda mungkin biasanya ingin menghasilkan jumlah sampel yang jauh lebih besar daripada hanya 255. Sebaliknya, untuk mengurangi kebisingan dalam data, sekitar 100.000 - atau bahkan puluhan juta, seperti yang disarankan dalam komentar lain, jika Anda ingin melihat kesalahan sekecil 0,78%.
— gak

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

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


6
Harap format ini lebih bermanfaat ( stackoverflow.com/editing-help ) dan tambahkan beberapa penjelasan. Jawaban hanya kode tidak terlalu dihargai. Menambahkan penjelasan akan membantu melawan kesalahpahaman bahwa StackOverflow adalah layanan penulisan kode gratis.
— Yunnosch

5

Terkesan oleh jawaban Kelvin, saya ingin menyarankan solusi yang agak mirip tetapi sedikit ditingkatkan.

var randomBoolean = Math.random() < 0.5;

Solusi ini sedikit lebih jelas untuk dibaca, karena angka di sebelah kanan memberi <tahu Anda kemungkinan mendapatkan truedaripada mendapatkan false, yang lebih alami untuk dipahami. Juga <satu simbol lebih pendek dari >=;


0

Bagaimana dengan yang ini?

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

1
OP menyatakan bahwa dia sudah menggunakan metode serupa, tidak perlu memposting ini.
— Jacob Gunther

-1

Jawaban Alexander O'Mara

hanya menambahkan cuplikan kode simpul

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);

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.