JS generiert zufällige Boolesche Werte

134

Einfache Frage, aber ich interessiere mich für die Nuancen hier.

Ich generiere zufällige Boolesche Werte mit der folgenden Methode, die ich mir ausgedacht habe:

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

Wann immer es random()auftaucht, scheint es immer eine Falle zu geben - es ist nicht wirklich zufällig, es wird durch irgendetwas kompromittiert usw. Also würde ich gerne wissen:

a) Ist das oben Genannte die beste Vorgehensweise?

b) Überdenke ich Dinge?

c) Denke ich Dinge?

d) Gibt es einen besseren / schnelleren / eleganteren Weg, den ich nicht kenne?

(Auch etwas interessiert, wenn sich B und C gegenseitig ausschließen.)

Aktualisieren

Wenn es einen Unterschied macht, verwende ich dies für die Bewegung eines KI-Charakters.

Ben
quelle
25
const rand = Math.random() < 0.5ist gleichwertig und einfacher.
Hamms
3
Sie können nur Pseudozufälligkeit erreichen , nicht wirklich Zufälligkeit.
Oriol
Nichts ist wirklich zufällig, das Ziel ist es, so nah wie möglich an den Zufall heranzukommen.
Adam Buchanan Smith
Und wenn Sie eine 50/50-Chance haben, math.randomsollte es genug sein. Verwenden Sie einfach Millisekunden für Ihren Samen.
Adam Buchanan Smith
Ich denke, es ist ziemlich zufällig, wenn man eine Website besucht: D, also hatte ich diese Idee ...Boolean(+Date.now()%2)
Roko C. Buljan

Antworten:

337

Technisch gesehen sieht der Code gut aus, ist aber etwas zu komplex. Sie können vergleichen , Math.random()um 0.5direkt als Bereich von Math.random()IS [0, 1)(dies bedeutet ‚im Bereich von 0 bis 1 einschließlich 0, aber nicht 1‘). Sie können den Bereich in [0, 0.5)und unterteilen [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
quelle
3
Ich mag diese eine Lösung, da sie es Ihnen ermöglicht, die Wahrscheinlichkeit von wahr / falsch zu optimieren
Evanion
Wenn Sie beispielsweise die Zahl 0,5 auf 0,9 ändern, erhöht dies die Wahrscheinlichkeit von Falsch und wie?
Agent Zebra
wenn Sie es von 0,5 auf 0,9 ändern. Dann wird sich die Wahrscheinlichkeit wahrscheinlich ändern. Ich denke, Sie können es mit einer großen Anzahl von Zufallsschleifen versuchen, wie 10000 Iterationen.
Kelvin
Für modernes JavaScript sollten Sie letdhlet randomBool = Math.random() >= 0.5;
Chris Halcrow
27

Wenn Ihr Projekt hat lodash, können Sie:

_.sample([true, false])
hthserhs
quelle
13

Für einen kryptografisch sichereren Wert können Sie ihn crypto.getRandomValuesin modernen Browsern verwenden.

Stichprobe:

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;

Beachten Sie, dass das cryptoObjekt eine DOM-API ist, daher in Node nicht verfügbar ist, es jedoch eine ähnliche API für Node gibt .

Alexander O'Mara
quelle
4
Math.random()ist in vielerlei Hinsicht notorisch zufällig, großartiger alternativer Vorschlag
Charles Harris
3
Ich werde hier nur eine kleine Korrektur hinzufügen, da ich nach 50 000 000 Läufen festgestellt habe, dass durchschnittlich 0,78% oder mehr Nullen generiert wurden: return a [0] <= 127; (
Sonst
2
@AmundMidtskog Guter Anruf. Ich hätte tippen sollen:a[0] > 127
Alexander O'Mara
1
Übrigens möchten Sie normalerweise eine viel größere Anzahl von Samples als nur 255 generieren. Um das Rauschen in den Daten zu reduzieren, etwa 100.000 - oder sogar zig Millionen, wie im anderen Kommentar vorgeschlagen, wenn Sie möchten Fehler von nur 0,78% sehen.
Caw
8
!Math.round(Math.random());

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

user12066722
quelle
6
Bitte formatieren Sie dies hilfreicher ( stackoverflow.com/editing-help ) und fügen Sie einige Erklärungen hinzu. Nur-Code-Antworten werden nicht sehr geschätzt. Das Hinzufügen einer Erklärung würde helfen, das Missverständnis zu bekämpfen, dass StackOverflow ein kostenloser Code-Schreibdienst ist.
Yunnosch
5

Von Kelvins Antwort sehr beeindruckt, möchte ich eine ziemlich ähnliche, aber leicht verbesserte Lösung vorschlagen.

var randomBoolean = Math.random() < 0.5;

Diese Lösung ist etwas offensichtlicher zu lesen, da die Zahl auf der rechten Seite <die Wahrscheinlichkeit des Erhaltens trueund nicht des Erhaltens angibt false, was natürlicher zu verstehen ist. Auch <ist ein Symbol kürzer als >=;

Arthur Khazbs
quelle
0

Wie wäre es mit diesem?

return Math.round((Math.random() * 1) + 0) === 0;
Alex
quelle
1
OP gibt an, dass er bereits ähnliche Methoden verwendet, ohne dass dies veröffentlicht werden muss.
Jacob Gunther
-1

Antwort von Alexander O'Mara

Fügen Sie einfach das Knotencode-Snippet hinzu

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
quelle