Генератор случайных чисел
Разбирал свою старую писанину - наткнулся на несложный генератор случайных чисел на препроцессоре M4. Позволяет генерировать целые псевдослучайные числа в заданном диапазоне на этапе сборки программы.
define('m4_ifval', 'ifelse('$1','','$3','$2')')
define('m4_default', 'm4_ifval('$1','$1','$2')')
dnl ========== m4_random(max=2796203) =================
define('m4$random$value',patsubst(substr(esyscmd(time /T),0,5),':'))
define('m4_random','define('m4$random$value',eval((indir('m4$random$value') * 125) % 2796203))eval((indir('m4$random$value')%m4_default('$1',2796203))+1)')
Попробуем:
Вызов | Результат |
m4_random() | 266751 |
m4_random() | 2585518 |
m4_random() | 1626281 |
m4_random(50) | 35 |
m4_random(50) | 40 |
m4_random(50) | 22 |
m4_random(50) | 6 |
m4_random(50) | 30 |
m4_random(50) | 33 |
m4_random(50) | 15 |
m4_random(5) | 1 |
m4_random(5) | 5 |
m4_random(5) | 2 |
m4_random(5) | 1 |
m4_random(5) | 4 |
Зачем понадобилось? Всякие вопросы секретности при генерации исходных текстов.
Другой вариант. Используются следующие идеи:
- mkstemp (или maketemp) создает уникальный файл с именем из 6 алфавитно-цифровых символов.
- eval позволяет интерпретировать эти символы как число с основанием 36.
- Чтобы не было переполнения 4-байтового long, с которым работает препроцессор m4, cтарший разряд полученного числа, равный Z(36), отбрасывается посредством patsubst.
- Остаток от деления позволяет выбрать верхнюю границу для создаваемых чисел.
define(`m4_trim_left',`patsubst(`$1',m4_default(`$2',`^ *'),`')')
define(`m4_random',`pushdef(`_', maketemp())syscmd(`del /Q' _)eval(0r36:m4_trim_left(_,`^[zZ]')%m4_default(`$1',2147483647))popdef(`_')')