JS генерують випадкові булі


134

Просте запитання, але мене тут цікавлять нюанси.

Я генерую випадкові булі, використовуючи наступний метод, який я придумав сам:

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

Кожен раз, коли random()з’являється, здається, що завжди є підводний камінь - це не справді випадково, це компрометується чимось чи іншим і т. Д. Отже, я хотів би знати:

а) Чи є вищезгаданим найкращим способом це зробити?

б) Чи я передумую речі?

в) чи я задумуюсь над речами?

г) Чи існує кращий / швидший / елегантний спосіб, про який я не знаю?

(Також дещо цікавить, якщо B і C взаємовиключні.)

Оновлення

Якщо це має значення, я використовую це для руху символу AI.


25
const rand = Math.random() < 0.5рівнозначний і простіший.
Хаммс

3
Ви можете досягти лише псевдовипадковості , а не справді випадковості.
Оріол

Насправді нічого не є випадковим, мета - наблизитися до випадкового, наскільки це можливо.
Адам Бюкенан Сміт

А якщо у вас шанс 50/50, math.randomмає бути багато. Просто використовуйте мілісекунди для свого насіння.
Адам Бюкенан Сміт

Я думаю, що це доволі випадково, коли я відвідую веб-сайт: D, тому я мав таке уявлення ...Boolean(+Date.now()%2)
Roko C. Buljan

Відповіді:


337

Технічно код виглядає чудово, але просто трохи складним. Ви можете порівняти Math.random()з 0.5безпосередньо, як діапазон Math.random()IS [0, 1)(це означає , що «в діапазоні від 0 до 1 , включаючи 0, але не 1»). Ви можете розділити діапазон на [0, 0.5)і [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
Мені подобається це одне рішення, оскільки воно дозволяє налаштувати вірогідність / хибність
Evanion

якщо, наприклад, змінити число 0,5 на 0,9, чи збільшує це ймовірність помилки, і як?
агент Зебра

якщо змінити його від 0,5 до 0,9. Тоді ймовірність, ймовірно, буде змінена. Я думаю, ви можете спробувати це з великою кількістю випадкових циклів, як 10000 ітерацій.
Келвін

Для сучасного JavaScript ви повинні використовувати, letтобтоlet randomBool = Math.random() >= 0.5;
Chris Halcrow


13

Для отримання більш криптографічно безпечного значення ви можете використовувати crypto.getRandomValuesв сучасних браузерах.

Зразок:

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;

Зауважте, що cryptoоб'єктом є API DOM, тому він недоступний у Node, але існує аналогічний API для Node .


4
Math.random()є сумнівно невипадковою у багатьох відношеннях чудовою альтернативною пропозицією
Чарльз Харріс

3
Я просто додам сюди невелику поправку, оскільки після 50 000 000 пробіжок я виявив, що вона генерувала в середньому 0,78% або більше нулів: return a [0] <= 127; (Інакше 127 ніколи не включається)
Амунд Мідського

2
@AmundMidtskog Добрий дзвінок. Я повинен був набрати:a[0] > 127
Олександр О'Мара

1
До речі, ви, як правило, захочете генерувати значно більшу кількість вибірок, ніж лише 255. Скоріше, щоб зменшити шум у даних, щось на зразок 100 000 - або навіть десятки мільйонів, як це запропоновано в іншому коментарі, якщо ви хочете бачити помилки лише на 0,78%.
каре

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

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


6
Будь ласка, відформатуйте це більш корисно ( stackoverflow.com/editing-help ) та додайте пояснення. Відповіді, що стосуються лише коду, не надто оцінені. Додавання пояснення допоможе боротися з оманою того, що StackOverflow - це безкоштовна послуга з написання коду.
Yunnosch

5

Дуже вражений відповіддю Кельвіна, я хотів би запропонувати досить схоже, але трохи вдосконалене рішення.

var randomBoolean = Math.random() < 0.5;

Це рішення трохи очевидніше для читання, оскільки число з правого боку <говорить вам про ймовірність отримати, trueа не отримати false, що є більш природним для розуміння. Також <один символ коротший >=;


0

Як щодо цього?

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

1
ОП заявляє, що він вже використовує подібні методи, не потрібно цього публікувати.
Яків Гюнтер

-1

Відповідь Олександра О'Мара

просто додавання фрагмента коду вузла

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.