Меню

Tilda генератор случайных чисел

Случайные числа

Я думаю понятие случайных чисел/величин вам знакомо: они случайны. Иногда в самодельном устройстве бывает нужна случайная величина, например для какой-нибудь игры или световых эффектов. Программный источник настоящих случайных чисел организовать весьма непросто, в отличие от аппаратного. Банально игральный кубик или лото-машина являются вполне себе хорошими источниками случайных чисел. Микроконтроллер к слову не может генерировать случайные числа, потому что он – точное вычислительное устройство, случайностей быть не может. Что делать? Использовать такое понятие, как псевдослучайные числа. Чем они отличаются от случайных? Своей природой. Псевдослучайное число получается путём различных математических действий с начальным числом, то есть имея начальное число, мы можем сгенерировать на его основе целую кучу других чисел. Но тут есть две проблемы:

  • Через какое-то количество чисел (тысяч, а может и миллиардов, а может и больше) ряд сгенерированных псевдослучайных чисел начнёт повторяться. Для наших целей это не так страшно, можно об этом не думать
  • Генератору псевдослучайных чисел нужно начальное случайное число. Вот это реально беда… Но ничего, у нашего микроконтроллера есть и аппаратные средства

Ардуино и случайные числа

Ардуино имеет пару готовых функций для работы с псевдослучайными числами, давайте на них посмотрим:

  • random(max); – возвращает псевдослучайное число в диапазоне от 0 до ( max – 1 ). max принимает unsigned long , то есть от 0 до 4 294 967 295
  • random(min, max); – возвращает псевдослучайное число в диапазоне от min до ( max – 1 ). max принимает unsigned long , то есть от 0 до 4 294 967 295
  • randomSeed(value); – дать генератору псевдослучайных чисел новую опорную точку для отсчёта. value – любое число типа unsigned long , значит на Ардуино мы имеем 2^32 (4 294 967 295) наборов псевдослучайных чисел. На ваш век этого точно хватит!
Читайте также:  Реле генератора ниссан тино

Как правильно генерировать случайные числа, чтобы последовательность каждый раз была новая? Есть варианты:

  • При запуске программы задавать случайное число в randomSeed() . Как это сделать? Расскажу ниже
  • Если устройство как-то взаимодействует со внешним миром, или даже с пользователем, то можно при наступлении некоторых аппаратно случайных событий (нажатие кнопки, срабатывание датчика, принятие данных, и т.д.) скармливать randomSeed‘у текущее время с момента старта программы, т.е. функции millis() или micros() . Отличное решение кстати! Банально вызываем randomSeed(micros()) и всё.

Аппаратный рандом

Помните, в уроке про цифровые пины я говорил, что если пин никуда не подключен – то он ловит “из воздуха” всякие наводки. Шумы имеют природу, близкую к случайной, и было бы глупо этим не воспользоваться! Давайте посмотрим, какие значения можно получить с никуда не подключенного аналогового пина, опрашивая его обычным analogRead();

Синусоида? Вполне логично, в стенах куча проводов с сетевым напряжением, вот они и наводят на микроконтроллер всякие помехи. Можно ли пользоваться сырым значением с аналогового пина в качестве “зерна” для randomSeed() ? Нужно! То есть при запуске устройства делать вот так:

Но есть ещё интересный вариант, который позволит получить гораздо более случайные числа для randomSeed() . Есть информация, что первые два бита из результата analogRead() имеют самый большой шум. Давайте на него посмотрим, выведя несколько (300) результатов в график. Получить первые два бита можно так: analogRead(A0) & 0b0000011 , или более коротко – analogRead(A0) & 3

Выглядит весьма случайно, никакой закономерности не прослеживается! Но значения меняются всего от 0 до 3. Поэтому можно попробовать их перемножать и складывать, примерно так:

Именно такой код я рекомендую использовать для получения случайного зерна для генератора случайных чисел при запуске программы. Напоследок давайте посмотрим, какой результат даёт такая конструкция:

Читайте также:  Как проверить возбудитель генератора ваз 2109

График я построил в excel, чтобы более чётко видеть рассеивание полученного случайного значения Имеем практически равномерное рассеяние и огромное количество случайных значений, полученных путём перемножения и сложения “шума”. Пользуйтесь на здоровье.

Случайный bool

Иногда бывает нужен случайный флаг, то есть true / false . Делается это очень просто: в уроке про условия я рассказывал, что bool ( boolean ) принимает true при любом отличном от нуля значении. Это можно использовать для получения случайного true / false с заданной вероятностью! Просто присваиваем логической переменной результат функции random() , в которую передаём число, обратное вероятности получения false :

Переменная rndFlag получит значение false с вероятностью 1/5, то есть 20%. Если нужен true с низкой вероятностью – используем инверсию:

Теперь переменная rndFlag получит значение true с вероятностью 10%.

Видео

Источник

Adblock
detector