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.