Math
Содержание:
- Синтаксис
- Перебор генераторов
- generator.throw
- How does Random.js alleviate these problems?
- Композиция генераторов
- Композиция генераторов
- Why is this needed?
- API
- How does Random.js alleviate these problems?
- yield – дорога в обе стороны
- Способы записи числа
- API
- Округление
- 1 Псевдослучайные числа
- Как в приложении Почта (Mail) отключить уведомления о новых сообщениях в почтовых ветках
- Extending
- Usage
- generator.throw
- Использование генераторов для перебираемых объектов
- Генератор псевдослучайных чисел и генератор случайных чисел
- Итого
Синтаксис
Math.random()
Возвращаемое значение
Число с плавающей точкой в диапазоне от 0 (включительно) до 1 (исключительно).
Метод Math.random() в основном используют для генерации псевдо-случайного числа в определённом диапазоне. Например, нам надо получить число в диапазоне от 50 до 100 (включительно). Для этого нам придётся написать следующий код:
document.write(Math.floor(Math.random() * 51 + 50));
Рассмотрим подробно как работает наш пример и почему используется именно такая форма записи. Первым делом нам надо указать минимальное получаемое значение из нужного диапазона, в нашем примере это число 50. Теперь нам нужно каким-то образом получить случайное число, которое при сложении с числом 50 не будет превышать в сумме число 100. Как мы знаем из математики, нахождение неизвестного слагаемого делается путём вычитания из суммы известного слагаемого. 100 — 50: получаем разность 50. Теперь для проверки, подходит нам это число или нет, умножим его на возможное минимальное и максимальное число возвращаемое методом Math.random(). Умножаем минимальное 0.004704564176082244 * 50 = 0.2… и максимальное 0.9999999999746223 * 50 = 49.9… И так мы видим, что при умножении разности на максимально возможное случайное число в результате даёт нам целую часть числа на единицу меньше, чем нужно. Чтобы исправить ситуацию, нам нужно всего лишь прибавить одну единицу к 50, т.е. 50 + 1 = 51, теперь если полученное число умножить на максимально возможно число возвращаемое методом у нас будет выходить число 50.9… — это то, что нам надо, после сложения чисел 50.9 + 50, получаем 100.9. Для округления числа до целого используем метод Math.floor(). Таким образом, формула для получения нужного числа выглядит следующим образом: max — min + 1. Перепишем приведённый выше пример:
var max = 100, min = 50; document.write(Math.floor(Math.random() * (max - min + 1) + min));
Эта формула особенно полезна, когда заранее неизвестно в каком диапазоне необходимо получить случайное число.
Пример
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Название документа</title> </head> <body> <p>Псевдослучайное число в диапазоне от 1 до 10.</p> <div id="test"></div> <script> var x; for(var i = 0; i < 10; i++) { x = document.getElementById('test'); x.innerHTML += Math.floor(Math.random() * 10 + 1) + '<br>'; } </script> </body> </html>
Попробовать »
Перебор генераторов
Как вы, наверное, уже догадались по наличию метода , генераторы являются перебираемыми объектами.
Возвращаемые ими значения можно перебирать через :
Выглядит гораздо красивее, чем использование , верно?
…Но обратите внимание: пример выше выводит значение , затем. Значение выведено не будет!. Это из-за того, что перебор через игнорирует последнее значение, при котором
Поэтому, если мы хотим, чтобы были все значения при переборе через , то надо возвращать их через :
Это из-за того, что перебор через игнорирует последнее значение, при котором . Поэтому, если мы хотим, чтобы были все значения при переборе через , то надо возвращать их через :
Так как генераторы являются перебираемыми объектами, мы можем использовать всю связанную с ними функциональность, например оператор расширения :
В коде выше превращает перебираемый объект-генератор в массив элементов (подробнее ознакомиться с оператором расширения можно в главе )
generator.throw
Как мы видели в примерах выше, внешний код может вернуть генератору в качестве результата любое значение.
…Но «вернуть» можно не только результат, но и ошибку!
Для того, чтобы передать в ошибку, используется вызов . При этом на строке с возникает исключение.
Например, в коде ниже обращение к внешнему коду завершится с ошибкой:
«Вброшенная» в строке ошибка возникает в строке с . Далее она обрабатывается как обычно. В примере выше она перехватывается и выводится.
Если ошибку не перехватить, то она «выпадет» из генератора. По стеку ближайший вызов, который инициировал выполнение – это строка с . Можно перехватить её там, как и продемонстрировано в примере ниже:
Если же ошибка и там не перехвачена, то дальше – как обычно, либо снаружи, либо она «повалит» скрипт.
How does Random.js alleviate these problems?
Random.js provides a set of «engines» for producing random integers, which consistently provide values within , i.e. 32 bits of randomness.
One is also free to implement their own engine as long as it returns 32-bit integers, either signed or unsigned.
Some common, biased, incorrect tool for generating random integers is as follows:
The problem with both of these approaches is that the distribution of integers that it returns is not uniform. That is, it might be more biased to return rather than , making it inherently broken.
may more evenly distribute its biased, but it is still wrong. , at least in the example given, is heavily biased to return over .
In order to eliminate bias, sometimes the engine which random data is pulled from may need to be used more than once.
Random.js provides a series of distributions to alleviate this.
Композиция генераторов
Композиция генераторов – это особенная возможность генераторов, которая позволяет прозрачно «встраивать» генераторы друг в друга.
Например, у нас есть функция для генерации последовательности чисел:
Мы хотели бы использовать её при генерации более сложной последовательности:
- сначала цифры (с кодами символов 48…57)
- за которыми следуют буквы в верхнем регистре (коды символов 65…90)
- за которыми следуют буквы алфавита (коды символов 97…122)
Мы можем использовать такую последовательность для генерации паролей, выбирать символы из неё (может быть, ещё добавить символы пунктуации), но сначала её нужно сгенерировать.
В обычной функции, чтобы объединить результаты из нескольких других функций, мы вызываем их, сохраняем промежуточные результаты, а затем в конце их объединяем.
Для генераторов есть особый синтаксис , который позволяет «вкладывать» генераторы один в другой (осуществлять их композицию).
Вот генератор с композицией:
Директива делегирует выполнение другому генератору. Этот термин означает, что перебирает генератор и прозрачно направляет его вывод наружу. Как если бы значения были сгенерированы внешним генератором.
Результат – такой же, как если бы мы встроили код из вложенных генераторов:
Композиция генераторов – естественный способ вставлять вывод одного генератора в поток другого. Она не использует дополнительную память для хранения промежуточных результатов.
Композиция генераторов
Один генератор может включать в себя другие. Это называется композицией.
Разберём композицию на примере.
Пусть у нас есть функция , которая генерирует последовательность чисел:
Мы хотим на её основе сделать другую функцию , которая будет генерировать коды для буквенно-цифровых символов латинского алфавита:
- – для
- – для
- – для
Далее этот набор кодов можно превратить в строку и использовать, к примеру, для выбора из него случайного пароля. Только символы пунктуации ещё хорошо бы добавить для надёжности, но в этом примере мы будем без них.
Естественно, раз в нашем распоряжении есть готовый генератор , то хорошо бы его использовать.
Конечно, можно внутри запустить несколько раз , объединить результаты и вернуть. Так мы бы сделали с обычными функциями. Но композиция – это кое-что получше.
Она выглядит так:
Здесь использована специальная форма . Она применима только к другому генератору и делегирует ему выполнение.
То есть, при интерпретатор переходит внутрь генератора-аргумента, к примеру, , выполняет его, и все , которые он делает, выходят из внешнего генератора.
Получается – как будто мы вставили код внутреннего генератора во внешний напрямую, вот так:
Код выше по поведению полностью идентичен варианту с . При этом, конечно, переменные вложенного генератора не попадают во внешний, «делегирование» только выводит результаты во внешний поток.
Композиция – это естественное встраивание одного генератора в поток другого. При композиции значения из вложенного генератора выдаются «по мере готовности». Поэтому она будет работать даже если поток данных из вложенного генератора оказался бесконечным или ожидает какого-либо условия для завершения.
Why is this needed?
Despite being capable of producing numbers within [0, 1), there are a few downsides to doing so:
- It is inconsistent between engines as to how many bits of randomness:
- Internet Explorer: 53 bits
- Mozilla Firefox: 53 bits
- Google Chrome/node.js: 32 bits
- Apple Safari: 32 bits
- It is non-deterministic, which means you can’t replay results consistently
- In older browsers, there can be manipulation through cross-frame random polling. This is mostly fixed in newer browsers and is required to be fixed in ECMAScript 6.
Also, and most crucially, most developers tend to use improper and biased logic as to generating integers within a uniform distribution.
API
Engines
- : Utilizes
- : Utilizes
- : Utilizes
- : Produces a new Mersenne Twister. Must be seeded before use.
Or you can make your own!
interface Engine { next(): number; // an int32 }
Any object that fulfills that interface is an .
Mersenne Twister API
- : Seed the twister with an initial 32-bit integer.
- : Seed the twister with an array of 32-bit integers.
- : Seed the twister with automatic information. This uses the current Date and other entropy sources.
- : Produce a 32-bit signed integer.
- : Discard random values. More efficient than running repeatedly.
- : Return the number of times the engine has been used plus the number of discarded values.
One can seed a Mersenne Twister with the same value () or values () and discard the number of uses () to achieve the exact same state.
If you wish to know the initial seed of , it is recommended to use the function to create the seed manually (this is what does under-the-hood).
const seed = createEntropy(); const mt = MersenneTwister19937.seedWithArray(seed); useTwisterALot(mt); // you'll have to implement this yourself const clone = MersenneTwister19937.seedWithArray(seed).discard( mt.getUseCount() ); // at this point, `mt` and `clone` will produce equivalent values
Distributions
Random.js also provides a set of methods for producing useful data from an engine.
- : Produce an integer within the inclusive range . can be at its minimum -9007199254740992 (-2 ** 53). can be at its maximum 9007199254740992 (2 ** 53).
- : Produce a floating point number within the range . Uses 53 bits of randomness.
- : Produce a boolean with a 50% chance of it being .
- : Produce a boolean with the specified chance causing it to be .
- : Produce a boolean with / chance of it being true.
- : Return a random value within the provided within the sliced bounds of and .
- : Same as .
- : Shuffle the provided (in-place). Similar to .
- : From the array, produce an array with elements that are randomly chosen without repeats.
- : Same as
- : Produce an array of length with as many rolls.
- : Produce a random string using numbers, uppercase and lowercase letters, , and of length .
- : Produce a random string using the provided string as the possible characters to choose from of length .
- or : Produce a random string comprised of numbers or the characters of length .
- : Produce a random string comprised of numbers or the characters of length .
- : Produce a random within the inclusive range of . and must both be s.
An example of using would be as such:
// create a Mersenne Twister-19937 that is auto-seeded based on time and other random values const engine = MersenneTwister19937.autoSeed(); // create a distribution that will consistently produce integers within inclusive range . const distribution = integer(, 99); // generate a number that is guaranteed to be within without any particular bias. function generateNaturalLessThan100() { return distribution(engine); }
Producing a distribution should be considered a cheap operation, but producing a new Mersenne Twister can be expensive.
An example of producing a random SHA1 hash:
// using essentially Math.random() var engine = nativeMath; // lower-case Hex string distribution var distribution = hex(false); // generate a 40-character hex string function generateSHA1() { return distribution(engine, 40); }
How does Random.js alleviate these problems?
Random.js provides a set of «engines» for producing random integers, which consistently provide values within , i.e. 32 bits of randomness.
One is also free to implement their own engine as long as it returns 32-bit integers, either signed or unsigned.
Some common, biased, incorrect tool for generating random integers is as follows:
The problem with both of these approaches is that the distribution of integers that it returns is not uniform. That is, it might be more biased to return rather than , making it inherently broken.
may more evenly distribute its biased, but it is still wrong. , at least in the example given, is heavily biased to return over .
In order to eliminate bias, sometimes the engine which random data is pulled from may need to be used more than once.
Random.js provides a series of distributions to alleviate this.
yield – дорога в обе стороны
До этого момента генераторы сильно напоминали перебираемые объекты, со специальным синтаксисом для генерации значений. Но на самом деле они намного мощнее и гибче.
Всё дело в том, что – дорога в обе стороны: он не только возвращает результат наружу, но и может передавать значение извне в генератор.
Чтобы это сделать, нам нужно вызвать с аргументом. Этот аргумент становится результатом .
Продемонстрируем это на примере:
- Первый вызов – всегда без аргумента, он начинает выполнение и возвращает результат первого . На этой точке генератор приостанавливает выполнение.
- Затем, как показано на картинке выше, результат переходит во внешний код в переменную .
- При выполнение генератора возобновляется, а выходит из присваивания как результат: .
Обратите внимание, что внешний код не обязан немедленно вызывать. Ему может потребоваться время
Это не проблема, генератор подождёт.
Например:
Как видно, в отличие от обычных функций, генератор может обмениваться результатами с вызывающим кодом, передавая значения в .
Чтобы сделать происходящее более очевидным, вот ещё один пример с большим количеством вызовов:
Картинка выполнения:
- Первый начинает выполнение… Оно доходит до первого .
- Результат возвращается во внешний код.
- Второй передаёт обратно в генератор как результат первого и возобновляет выполнение.
- …Оно доходит до второго , который станет результатом .
- Третий передаёт в генератор как результат второго и возобновляет выполнение, которое завершается окончанием функции, так что .
Получается такой «пинг-понг»: каждый передаёт в генератор значение, которое становится результатом текущего , возобновляет выполнение и получает выражение из следующего .
Способы записи числа
Представьте, что нам надо записать число 1 миллиард. Самый очевидный путь:
Но в реальной жизни мы обычно опускаем запись множества нулей, так как можно легко ошибиться. Укороченная запись может выглядеть как или для 7 миллиардов 300 миллионов. Такой принцип работает для всех больших чисел.
В JavaScript можно использовать букву , чтобы укоротить запись числа. Она добавляется к числу и заменяет указанное количество нулей:
Другими словами, производит операцию умножения числа на 1 с указанным количеством нулей.
Сейчас давайте запишем что-нибудь очень маленькое. К примеру, 1 микросекунду (одна миллионная секунды):
Записать микросекунду в укороченном виде нам поможет .
Если мы подсчитаем количество нулей , их будет 6. Естественно, верная запись .
Другими словами, отрицательное число после подразумевает деление на 1 с указанным количеством нулей:
Шестнадцатеричные числа широко используются в JavaScript для представления цветов, кодировки символов и многого другого. Естественно, есть короткий стиль записи: , после которого указывается число.
Например:
Не так часто используются двоичные и восьмеричные числа, но они также поддерживаются для двоичных и для восьмеричных:
Есть только 3 системы счисления с такой поддержкой. Для других систем счисления мы рекомендуем использовать функцию (рассмотрим позже в этой главе).
API
- : Utilizes
- : Utilizes
- : Utilizes
- : Produces a new Mersenne Twister. Must be seeded before use.
Or you can make your own!
interfaceEngine{next()number;}
Any object that fulfills that interface is an .
- : Seed the twister with an initial 32-bit integer.
- : Seed the twister with an array of 32-bit integers.
- : Seed the twister with automatic information. This uses the current Date and other entropy sources.
- : Produce a 32-bit signed integer.
- : Discard random values. More efficient than running repeatedly.
- : Return the number of times the engine has been used plus the number of discarded values.
One can seed a Mersenne Twister with the same value () or values () and discard the number of uses () to achieve the exact same state.
If you wish to know the initial seed of , it is recommended to use the function to create the seed manually (this is what does under-the-hood).
constseed=createEntropy();constmt=MersenneTwister19937.seedWithArray(seed);useTwisterALot(mt);constclone=MersenneTwister19937.seedWithArray(seed).discard(mt.getUseCount());
Random.js also provides a set of methods for producing useful data from an engine.
- : Produce an integer within the inclusive range . can be at its minimum -9007199254740992 (-2 ** 53). can be at its maximum 9007199254740992 (2 ** 53).
- : Produce a floating point number within the range . Uses 53 bits of randomness.
- : Produce a boolean with a 50% chance of it being .
- : Produce a boolean with the specified chance causing it to be .
- : Produce a boolean with / chance of it being true.
- : Return a random value within the provided within the sliced bounds of and .
- : Same as .
- : Shuffle the provided (in-place). Similar to .
- : From the array, produce an array with elements that are randomly chosen without repeats.
- : Same as
- : Produce an array of length with as many rolls.
- : Produce a random string using numbers, uppercase and lowercase letters, , and of length .
- : Produce a random string using the provided string as the possible characters to choose from of length .
- or : Produce a random string comprised of numbers or the characters of length .
- : Produce a random string comprised of numbers or the characters of length .
- : Produce a random within the inclusive range of . and must both be s.
An example of using would be as such:
constengine=MersenneTwister19937.autoSeed();constdistribution=integer(,99);functiongenerateNaturalLessThan100(){returndistribution(engine);}
Producing a distribution should be considered a cheap operation, but producing a new Mersenne Twister can be expensive.
An example of producing a random SHA1 hash:
var engine = nativeMath;var distribution =hex(false);functiongenerateSHA1(){returndistribution(engine,40);}
Округление
Одна из часто используемых операций при работе с числами – это округление.
В JavaScript есть несколько встроенных функций для работы с округлением:
- Округление в меньшую сторону: становится , а — .
- Округление в большую сторону: становится , а — .
- Округление до ближайшего целого: становится , — , а — .
- (не поддерживается в Internet Explorer)
- Производит удаление дробной части без округления: становится , а — .
Ниже представлена таблица с различиями между функциями округления:
Эти функции охватывают все возможные способы обработки десятичной части. Что если нам надо округлить число до количества цифр в дробной части?
Например, у нас есть и мы хотим округлить число до 2-х знаков после запятой, оставить только .
Есть два пути решения:
Умножить и разделить.
Например, чтобы округлить число до второго знака после запятой, мы можем умножить число на , вызвать функцию округления и разделить обратно.
Метод toFixed(n) округляет число до знаков после запятой и возвращает строковое представление результата.
Округляет значение до ближайшего числа, как в большую, так и в меньшую сторону, аналогично методу :
Обратите внимание, что результатом является строка. Если десятичная часть короче, чем необходима, будут добавлены нули в конец строки:
Мы можем преобразовать полученное значение в число, используя унарный оператор или , пример с унарным оператором: .
1 Псевдослучайные числа
Иногда программист сталкивается с простыми, казалось бы, задачами: «отобрать случайный фильм для вечернего просмотра из определенного списка», «выбрать победителя лотереи», «перемешать список песен при тряске смартфона», «выбрать случайное число для шифрования сообщения», и каждый раз у него возникает очень закономерный вопрос: а как получить это самое случайное число?
Вообще-то, если вам нужно получить «настоящее случайное число», сделать это довольно-таки трудно. Вплоть до того, что в компьютер встраивают специальные математические сопроцессоры, которые умеют генерировать такие числа, с выполнением всех требований к «истинной случайности».
Поэтому программисты придумали свое решение — псевдослучайные числа. Псевдослучайные числа — это некая последовательность, числа в которой на первый взгляд кажутся случайными, но специалист при детальном анализе сможет найти в них определенные закономерности. Для шифрования секретных документов такие числа не подойдут, а для имитации бросания кубика в игре — вполне.
Есть много алгоритмов генерации последовательности псевдослучайных чисел и почти все из них генерируют следующее случайное число на основе предыдущего и еще каких-то вспомогательных чисел.
Например, данная программа выведет на экран неповторяющихся чисел:
Кстати, мы говорим не о псевдослучайных числах, а именно о последовательности таких чисел. Т.к. глядя на одно число невозможно понять, случайное оно или нет.
Случайное число ведь можно получить разными способами:
Как в приложении Почта (Mail) отключить уведомления о новых сообщениях в почтовых ветках
Для отключения сообщений в любой ветке электронной почты в приложении Почта выполните следующие действия:
1. Запустите стандартное почтовое приложение на iPhone или iPad с iOS 13 или более поздних версий.
2. Найдите ветку сообщений электронной почты, уведомления для которой вы хотите отключить.
3. Проведите пальцем влево по верхнему сообщению ветки, чтобы отобразить скрытые действия, и нажмите «Еще».
4. Во всплывающем меню нажмите на «Не уведомлять».
Это отключит оповещения для всей выбранной ветки на всех ваших устройствах Apple, работающих с одинаковой учетной записью iCloud. В дальнейшем вы уже не будете получать уведомления каждый раз при появлении в этой цепочке нового сообщения. Программа Mail пометит приглушенные ветки маленьким значком колокольчика с диагональной линией. Это даст возможность быстро отделить приглушенные цепочки от обычных.
ПО ТЕМЕ: iOS 13: Новые эффекты и инструменты для обработки и редактирования фото и видео на iPhone и iPad.
Extending
You can add your own methods to instances, as such:
var random = new Random(); random.bark = function() { if (this.bool()) { return "arf!"; } else { return "woof!"; } }; random.bark(); //=> "arf!" or "woof!"
This is the recommended approach, especially if you only use one instance of .
Or you could even make your own subclass of Random:
function MyRandom(engine) { return Random.call(this, engine); } MyRandom.prototype = Object.create(Random.prototype); MyRandom.prototype.constructor = MyRandom; MyRandom.prototype.mood = function() { switch (this.integer(, 2)) { case : return "Happy"; case 1: return "Content"; case 2: return "Sad"; } }; var random = new MyRandom(); random.mood(); //=> "Happy", "Content", or "Sad"
Or, if you have a build tool are are in an ES6+ environment:
class MyRandom extends Random { mood() { switch (this.integer(, 2)) { case : return "Happy"; case 1: return "Content"; case 2: return "Sad"; } } } const random = new MyRandom(); random.mood(); //=> "Happy", "Content", or "Sad"
Usage
node.js
In your project, run the following command:
npm install random-js
or
yarn add random-js
In your code:
// ES6 Modules import { Random } from "random-js"; const random = new Random(); // uses the nativeMath engine const value = random.integer(1, 100);
// CommonJS Modules const { Random } = require("random-js"); const random = new Random(); // uses the nativeMath engine const value = random.integer(1, 100);
Or to have more control:
const Random = require("random-js").Random; const random = new Random(MersenneTwister19937.autoSeed()); const value = random.integer(1, 100);
It is recommended to create one shared engine and/or instance per-process rather than one per file.
Browser using AMD or RequireJS
Download and place it in your project, then use one of the following patterns:
define(function(require) { var Random = require("random"); return new Random.Random(Random.MersenneTwister19937.autoSeed()); }); define(function(require) { var Random = require("random"); return new Random.Random(); }); define("random", function(Random) { return new Random.Random(Random.MersenneTwister19937.autoSeed()); });
Browser using tag
Download and place it in your project, then add it as a tag as such:
<script src="lib/random-js.min.js"></script> <script> // Random is now available as a global (on the window object) var random = new Random.Random(); alert("Random value from 1 to 100: " + random.integer(1, 100)); </script>
generator.throw
Как мы видели в примерах выше, внешний код может передавать значение в генератор как результат .
…Но можно передать не только результат, но и инициировать ошибку. Это естественно, так как ошибка является своего рода результатом.
Для того, чтобы передать ошибку в , нам нужно вызвать . В таком случае исключение возникнет на строке с .
Например, здесь приведёт к ошибке:
Ошибка, которая проброшена в генератор на строке , приводит к исключению на строке с . В примере выше перехватывает её и отображает.
Если мы не хотим перехватывать её, то она, как и любое обычное исключение, «вывалится» из генератора во внешний код.
Текущая строка вызывающего кода – это строка с , отмечена . Таким образом, мы можем отловить её во внешнем коде, как здесь:
Если же ошибка и там не перехвачена, то дальше – как обычно, она выпадает наружу и, если не перехвачена, «повалит» скрипт.
Использование генераторов для перебираемых объектов
Некоторое время назад, в главе Перебираемые объекты, мы создали перебираемый объект , который возвращает значения .
Давайте вспомним код:
Мы можем использовать функцию-генератор для итерации, указав её в .
Вот тот же , но с гораздо более компактным итератором:
Это работает, потому что теперь возвращает генератор, и его методы – в точности то, что ожидает :
- у него есть метод
- который возвращает значения в виде
Это не совпадение, конечно. Генераторы были добавлены в язык JavaScript, в частности, с целью упростить создание перебираемых объектов.
Вариант с генератором намного короче, чем исходный вариант перебираемого , и сохраняет те же функциональные возможности.
Генераторы могут генерировать бесконечно
В примерах выше мы генерировали конечные последовательности, но мы также можем сделать генератор, который будет возвращать значения бесконечно. Например, бесконечная последовательность псевдослучайных чисел.
Конечно, нам потребуется (или ) в цикле по такому генератору, иначе цикл будет продолжаться бесконечно, и скрипт «зависнет».
Генератор псевдослучайных чисел и генератор случайных чисел
Для того, чтобы получить что-то случайное, нам нужен источник энтропии, источник некого хаоса из который мы будем использовать для генерации случайности.
Этот источник используется для накопления энтропии с последующим получением из неё начального значения (initial value, seed), которое необходимо генераторам случайных чисел (ГСЧ) для формирования случайных чисел.
Генератор ПсевдоСлучайных Чисел использует единственное начальное значение, откуда и следует его псевдослучайность, в то время как Генератор Случайных Чисел всегда формирует случайное число, имея в начале высококачественную случайную величину, которая берется из различных источников энтропии.
Выходит, что чтобы создать псевдослучайную последовательность нам нужен алгоритм, который будет генерить некоторую последовательность на основании определенной формулы. Но такую последовательность можно будет предсказать. Тем не менее, давайте пофантазируем, как бы могли написать свой генератор случайных чисел, если бы у нас не было Math.random()
ГПСЧ имеет некоторый алгоритм, который можно воспроизвести.
ГСЧ — это получение чисел полностью из какого либо шума, возможность просчитать который стремится к нулю. При этом в ГСЧ есть определенные алгоритмы для выравнивания распределения.
Итого
- Генераторы создаются при помощи функций-генераторов .
- Внутри генераторов и только внутри них существует оператор .
- Внешний код и генератор обмениваются промежуточными результатами посредством вызовов .
В современном JavaScript генераторы используются редко. Но иногда они оказываются полезными, потому что способность функции обмениваться данными с вызывающим кодом во время выполнения совершенно уникальна. И, конечно, для создания перебираемых объектов.
Также, в следующей главе мы будем изучать асинхронные генераторы, которые используются, чтобы читать потоки асинхронно сгенерированных данных (например, постранично загружаемые из сети) в цикле .
В веб-программировании мы часто работаем с потоками данных, так что это ещё один важный случай использования.