JS rastgele boole oluşturur


136

Basit bir soru, ama buradaki nüanslarla ilgileniyorum.

Bulduğum aşağıdaki yöntemi kullanarak rastgele booleler oluşturuyorum:

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

Ne zaman random()ortaya çıksa, her zaman bir tuzak var gibi görünüyor - bu gerçekten rastgele değil, bir şey veya başka bir şey tarafından tehlikeye atılıyor, vb. Yani bilmek istiyorum:

a) Yukarıdakiler bunu yapmanın en iyi uygulama yolu mu?

b) Bir şeyleri fazla mı düşünüyorum?

c) Bir şeyleri anlamıyor muyum?

d) Bilmediğim daha iyi / daha hızlı / daha zarif bir yol var mı?

(Ayrıca B ve C'nin birbirini dışlamasıyla da biraz ilgilenir.)

Güncelleme

Bir fark yaratırsa, bunu bir AI karakterinin hareketi için kullanıyorum.


26
const rand = Math.random() < 0.5eşdeğer ve daha basittir.
— Hamms

3
Gerçek rastgeleliği değil , yalnızca sözde rastlantısallığı elde edebilirsiniz .
— Oriol

Aslında hiçbir şey rastgele değildir, amaç mümkün olduğunca rastgele yaklaşmaktır.
— Adam Buchanan Smith

Ve 50/50 şansınız varsa, math.randombol olmalıdır. Tohumunuz için sadece milisaniye kullanın.
— Adam Buchanan Smith

Bir web sitesini ziyaret etmenin oldukça rastgele olduğunu düşünüyorum: D yani bu fikrim vardı ...Boolean(+Date.now()%2)
— Roko C. Buljan

Yanıtlar:


341

Teknik olarak kod iyi görünüyor, ancak biraz fazla karmaşık. Sen karşılaştırabilirsiniz Math.random()için 0.5aralığında olduğu, doğrudanMath.random() IS [0, 1)( '0 dahil 1'e 0'dan değil 1' demek olduğunu). Aralığı [0, 0.5)ve olarak bölebilirsiniz [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
Doğru / yanlış olasılığını ayarlamanıza izin verdiği için bu çözümü beğendim
— Evanion 14-19

Örneğin 0,5 sayısını 0,9 olarak değiştirirseniz, bu yanlış olma olasılığını artırır mı ve nasıl?
— Ajan Zebra

0,5'ten 0,9'a değiştirirseniz. Daha sonra olasılık muhtemelen değişecektir. Sanırım 10000 yineleme gibi çok sayıda rastgele döngü ile deneyebilirsiniz.
— Kelvin

Modern JavaScript için letie kullanmalısınızlet randomBool = Math.random() >= 0.5;
— Chris Halcrow

Neden <bunun yerine kullanmıyorsunuz >=? Math.random() < 0.5düşük yarı için 0,5 ve yüksek yarı için 1 hariç - yani yine de tam olarak% 50 şans. Artı, daha kısa. Ve bence, Math.random() < 0.1"% 10 gerçek şansı" olarak okumaktan daha sezgisel Math.random() >= 0.9. Sanırım bu oldukça seçici. Güzel cevap.
— Aaron Plocharczyk


13

Daha kriptografik olarak güvenli bir değer için kullanabilirsiniz crypto.getRandomValues için modern tarayıcılarda .

Örneklem:

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;

Not olduğunu cryptoo Düğüm mevcut değil, ama böylece nesne, DOM API'sıdır Düğüm için benzer bir API var .


4
Math.random()pek çok yönden rastgele değil, harika bir alternatif öneri
— Charles Harris

3
Burada küçük bir düzeltme ekleyeceğim, 50 000 000 çalıştırmadan sonra ortalama% 0,78 veya daha fazla sıfır ürettiğini keşfettim: a [0] <= 127; (Else 127 asla dahil edilmez)
— Amund Midtskog

2
@AmundMidtskog İyi çağrı. a[0] > 127
— Yazmalıydım

1
Bu arada, genellikle 255'ten çok daha fazla sayıda örnek oluşturmak isteyebilirsiniz. Bunun yerine, verilerdeki gürültüyü azaltmak için, 100.000 gibi bir şey - hatta diğer yorumda önerildiği gibi on milyonlarca % 0,78 kadar küçük hataları görmek istiyorsunuz.
— gak

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

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


6
Lütfen bunu daha faydalı bir şekilde biçimlendirin ( stackoverflow.com/editing-help ) ve biraz açıklama ekleyin. Yalnızca kod yanıtları pek takdir edilmiyor. Bir açıklama eklemek, StackOverflow'un ücretsiz bir kod yazma hizmeti olduğu yanılgısıyla mücadeleye yardımcı olur.
— Yunnosch

5

Kelvin'in cevabından çok etkilendim Oldukça benzer ancak biraz geliştirilmiş bir çözüm önermek istiyorum.

var randomBoolean = Math.random() < 0.5;

Sağ taraftaki numara çünkü bu çözüm, biraz daha belirgin okumaktır <size alma olasılığını söyler truealma yerine falsekavrar daha doğal olan. Ayrıca <şundan daha kısa bir semboldür >=;


1

Potansiyel olarak daha hızlı çözüm ...

Az önce düşündüğüm Bitwise operatör yaklaşımını da düşünebilirsiniz, Math.random() + .5 >> 0daha hızlı olup olmadığından emin değilsiniz, ancak burada kendiniz için test etmeniz gereken bir performans testi var .

let randomBoolean = Math.random() + .5 >> 0;
const randomBoolean = chance => Math.random() + chance >> 0;

Rasgele boole'sini almak için en yaygın yoludur Math.random() >= .5gelen Kelvin'in cevap

let randomBoolean = Math.random() >= .5;       
const randomBoolean = chance => Math.random() >= chance;

Math.round(Math.random())Yaklaşımı kullanmanın tek nedeni basitlik ve tembelliktir.


Bunun belirtmeye değip değmeyeceğinden emin değilim ama(.49999999999999997 >= .5) != (.49999999999999997+ .5 >> 0)
— Aaron Plocharczyk

Evet ama her iki yaklaşım da bu düzeyde yanlış, bu yüzden çok önemli olduğunu düşünmüyorum. (.49999999999999997 >=.5) == (.49999999999999991 +.5>>0)ve bu (.49999999999999998 >=.5) == (.49999999999999992 +.5>>0)her ikisi de doğrudur. Ayrıca bitsel sürümde doğru olma şansını tanımlarken, karşılaştırmalı örnek yanlış elde etme şansını tanımlıyoruz. Yani .2, bitsel olarak yaklaşık% 20 doğru şansa veya karşılaştırmalı yaklaşımda% 20
— yanlışa eşit olur

0

Buna ne dersin?

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

1
OP zaten benzer yöntemler kullandığını, bunu yayınlamaya gerek olmadığını belirtiyor.
— Jacob Gunther

-1

Alexander O'Mara'nın cevabı

sadece düğüm kod pasajı eklemek

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.