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.

Ben
sumber
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"

Kelvin
sumber
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
27

Jika proyek Anda selesai, lodashAnda dapat:

_.sample([true, false])
hthserhs
sumber
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 .

Alexander O'Mara
sumber
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());

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

pengguna12066722
sumber
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 >=;

Arthur Khazbs
sumber
0

Bagaimana dengan yang ini?

return Math.round((Math.random() * 1) + 0) === 0;
Alex
sumber
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);

bFunc
sumber