JS génère un booléen aléatoire


135

Question simple, mais je suis intéressé par les nuances ici.

Je génère des booléens aléatoires en utilisant la méthode suivante que j'ai inventée moi-même:

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

Chaque fois que cela se random()présente, il semble qu'il y ait toujours un écueil - ce n'est pas vraiment aléatoire, c'est compromis par quelque chose ou autre, etc. Donc, j'aimerais savoir:

a) Est-ce que ce qui précède est la meilleure façon de procéder?

b) Est-ce que je réfléchis trop aux choses?

c) Est-ce que je réfléchis aux choses?

d) Y a-t-il un moyen meilleur / plus rapide / élégant que je ne connais pas?

(Aussi un peu intéressé si B et C sont mutuellement exclusifs.)

Mettre à jour

Si cela fait une différence, j'utilise ceci pour le mouvement d'un personnage IA.


26
const rand = Math.random() < 0.5est équivalent et plus simple.
— Hamms

3
Vous ne pouvez obtenir que du pseudo - aléatoire , pas vraiment du hasard.
— Oriol

Rien n'est en fait aléatoire, le but est de se rapprocher le plus possible du hasard.
— Adam Buchanan Smith

Et si vous avez une chance de 50/50, cela math.randomdevrait être suffisant. Utilisez simplement des millisecondes pour votre graine.
— Adam Buchanan Smith

Je pense que c'est assez aléatoire le temps que l'on visite un site web: D alors j'ai eu cette idée ...Boolean(+Date.now()%2)
— Roko C. Buljan

Réponses:


340

Techniquement, le code semble correct, mais juste un peu trop complexe. Vous pouvez comparer Math.random()à 0.5directement, comme la gamme de Math.random()est - [0, 1)(ce qui signifie « dans la plage de 0 à 1 , y compris 0, mais pas 1 »). Vous pouvez diviser la plage en [0, 0.5)et [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
J'aime cette solution unique, car elle vous permet de modifier la probabilité de vrai / faux
— Evanion

si vous changez le nombre de 0,5 à 0,9 par exemple, cela augmente-t-il la probabilité de faux, et comment?
— Agent Zebra

si vous le changez de 0,5 à 0,9. Ensuite, la probabilité est susceptible d'être modifiée. Je pense que vous pouvez l'essayer avec un grand nombre de boucles aléatoires, comme 10000 itérations.
— Kelvin

Pour JavaScript moderne, vous devez utiliser letielet randomBool = Math.random() >= 0.5;
— Chris Halcrow

Pourquoi ne pas utiliser juste <au lieu de >=? Math.random() < 0.5est exclusif de 0,5 pour la moitié basse et exclusif de 1 pour la moitié haute - donc c'est toujours exactement une chance de 50%. De plus, c'est plus court. Et à mon avis, Math.random() < 0.1est plus intuitif à lire comme "10% de chance de vrai" que Math.random() >= 0.9. Je suppose que c'est assez difficile cependant. Bonne réponse.
— Aaron Plocharczyk il y a


13

Pour une valeur plus sécurisée cryptographiquement, vous pouvez utiliser crypto.getRandomValuesdans les navigateurs modernes.

Échantillon:

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;

Notez que l' cryptoobjet est une API DOM, il n'est donc pas disponible dans Node, mais il existe une API similaire pour Node .


4
Math.random()est notoirement non aléatoire à bien des égards, excellente suggestion alternative
— Charles Harris

3
Je vais juste ajouter une petite correction ici, comme je l'ai découvert après 50 000 000 d'exécutions qu'il a généré en moyenne 0,78% ou plus de zéros en plus: retourne un [0] <= 127; (Sinon 127 n'est jamais inclus)
— Amund Midtskog

2
@AmundMidtskog Bon appel. J'aurais dû taper:a[0] > 127
— Alexander O'Mara

1
À propos, vous voudrez peut-être généralement générer un nombre beaucoup plus grand d'échantillons que 255. Au lieu de cela, afin de réduire le bruit dans les données, quelque chose comme 100 000 - voire des dizaines de millions, comme suggéré dans l'autre commentaire, si vous voulez voir des erreurs aussi petites que 0,78%.
— caw

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

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


6
Veuillez formater cela plus utilement ( stackoverflow.com/editing-help ) et ajouter quelques explications. Les réponses basées uniquement sur le code ne sont pas très appréciées. L'ajout d'une explication aiderait à combattre l'idée fausse selon laquelle StackOverflow est un service d'écriture de code gratuit.
— Yunnosch le

5

Impressionné par la réponse de Kelvin, je voudrais suggérer une solution assez similaire mais légèrement améliorée.

var randomBoolean = Math.random() < 0.5;

Cette solution est un peu plus évidente à lire, car le nombre à droite de <vous indique la probabilité d'obtenir trueplutôt que d'obtenir false, ce qui est plus naturel à comprendre. <Un symbole est également plus court que >=;


1

Solution potentiellement plus rapide ...

Vous pouvez également envisager l'approche d'opérateur Bitwise à laquelle je viens de penser Math.random() + .5 >> 0, je ne sais pas si c'est plus rapide, mais voici un test de performance à tester par vous-même.

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

Le moyen le plus courant d'obtenir un booléen aléatoire est la réponseMath.random() >= .5 de Kelvin

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

La seule raison d'utiliser cette Math.round(Math.random())approche est la simplicité et la paresse.


Je ne sais pas si cela vaut la peine d'être souligné, mais(.49999999999999997 >= .5) != (.49999999999999997+ .5 >> 0)
— Aaron Plocharczyk il y a

Eh bien oui, mais les deux approches sont inexactes à ce niveau, donc je ne pense pas que cela compte trop. (.49999999999999997 >=.5) == (.49999999999999991 +.5>>0)et (.49999999999999998 >=.5) == (.49999999999999992 +.5>>0)c'est à la fois vrai. Également dans la version bit à bit, nous définissons la chance d'obtenir vrai, tandis que l'exemple comparatif nous définissons la chance d'obtenir faux. Donc .2 équivaudrait à environ 20% de chance de vrai dans le bit, ou à 20% de faux dans l'approche comparative.
— LeonNikolai il y a

0

Celui-ci, ça va?

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

1
OP déclare qu'il utilise déjà des méthodes similaires, pas besoin de poster cela.
— Jacob Gunther

-1

Réponse d' Alexandre O'Mara

ajouter simplement un extrait de code de nœud

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

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.