PyCustomRand — это Python-библиотека для генерации псевдослучайных чисел, основанная на алгоритме, использующем системное время с наносекундной точностью.
Данный авторский проект создан для изучения алгоритмов и альтернативных подходов к генерации случайных чисел и их округлении.
Меня не устраивало, что модуль random в Python генерирует недостаточно случайные числа ( особенно при нескольких последовательных генерациях ), а встроенный в Python модуль round довольно "грубо" округляет числа ( round(1.5) = 2 и в то же время round(2.5) = 2 ), поэтому я решил написать свою библиотеку для генерации псевдослучайных чисел — более простую и с наибольшей энтропией.
Warning
PyCustomRand не является криптографически стойкой библиотекой и не предназначена для использования в системах безопасности! Используйте secrets модуль.
PyCustomRand писался как альтернатива этим двум встроенным модулям. Вот главные особенности и возможности библиотеки:
- Данная библиотека проще написана — весь код закомментирован, лёгок и понятен. В основе реализации генератора псевдослучайных чисел лежит несложный алгоритм (использующий системное время) поэтому библиотеку легко кастомизировать/расширять/дополнять под себя.
- В большинстве своём PyCustomRand выдаёт более "энтропичный" результат при нескольких генерациях подряд по сравнению со встроенным
random-модулем.-
Сравнение с диаграммами
PyCustomRand демонстрирует на 173% более высокую кучность распределения по сравнению со стандартной библиотекой
randomв тестах на 1,000,000 итераций.Данные для диаграммы брались из тестирования, которое проводилось с помощью встроенного модуля диагностики (
check_distribution). По результатам PyCustomRand показал максимальное отклонение в 2.7 раза меньше, чем стандартныйrandom(0.0267% против 0.0730%).PyCustomRand Python Built-in
-
- Библиотека включает в себя все самые главные функции из оригинальной Python-библиотеки, но только местами улучшенные и упрощённые (например:
random_integerможет выдавать сгенерированный результат, делимый на заданное число из диапазона; результат функцииrandom_floatможно округлять и пр.)-
Список функций
- Генерация целых чисел (
random_integer,randrange,gen_random_number). - Генерация вещественных чисел (
random,random_float). - Поддержка статистических распределений: Нормальное (Гаусс), Треугольное, Экспоненциальное, Биномиальное.
- Инструменты для последовательностей: выбор случайного элемента (
choice), выборка с весами (choices), перемешивание (shuffle) и выборка уникальных элементов (sample). - Инициализация («посев») последовательности генератора псевдослучайных чисел (
set_seed,_get_next_seed_state).
- Генерация целых чисел (
-
- Также библиотека имеет дополнительные утилиты, полезные для разработки веба/игр: генерация UUID v4, случайных HEX-цветов (например,
#ff05a1), случайных байт, случайных булевых значений (True/False) с настраиваемым шансом. - Имеется модуль собственного честного округления —
true_round. Функция округляет числа привычным математическим способом (0.5 всегда вверх по модулю), а также исправляет погрешности плавающей точки (например, "проблему 2.675"). - Код покрыт unit-тестами (чему соответствует badge в начале README), также имеется встроенный модуль диагностики (
check_distribution), который позволяет в любой момент проверить равномерность распределения генератора.
Да, у проекта всё же имеются некоторые минусы:
- Рандом, основанный на времени, требует небольшого ожидания (
time.sleep()на 0.1 микросекунду), соответственно, при гигантских итерациях PyCustomRand будет уступать встроенному модулюrandomво времени. - Некоторые функции библиотеки PyCustomRand (функции выборки, распределений) настолько просто написаны, что могут быть недостаточно оптимизированными для гигантских выборок (+ добавляется накапливающееся микро-ожидание из-за проблемы выше).
Установка библиотеки происходит через стандартный менеджер пакетов для Python:
pip install pycustomrand➕ Альтернативные способы установки
-
Скачивание пакета на официальной странице PyPI: https://pypi.org/project/pycustomrand/#files
-
Скачивание пакета напрямую в разделе Releases: https://github.com/n1xsi/PyCustomRand/releases
-
Клонирование репозитория:
git clone https://github.com/n1xsi/PyCustomRand.gitНиже представлено описание всех доступных функций библиотеки с примерами. Для удобства они могут импороваться напрямую из пакета (from pycustomrand import FUNC_NAME).
Инициализация генератора позволяет получать воспроизводимые последовательности (например, для тестов или сохранения генерации мира).
-
set_seed(seed=None)Устанавливает начальное состояние генератора.seed: Любой объект, который преобразуется в строку — число/строка/список и др. ЕслиNone— используется системное время (случайная последовательность).
-
_get_next_seed_state(current_seed)Внутренняя функция для обновления состояния сида (LCG алгоритм).
🧩 Примеры 1
from pycustomrand import set_seed, random
print(random()) # Случайное число, например, 0.3730190220377659
set_seed("test") # Установление сида для тестов
print(random()) # Первый результат функции после установления сида "test" ВСЕГДА будет 0.1647608190844912
print(random()) # Второй результат функции тоже ВСЕГДА будет 0.943716375817365 (применилась функция _get_next_seed_state(current_seed="test"))
set_seed() # Обнуление сида
print(random()) # Случайное число, например, 0.2458062256227575-
gen_random_number(length=1)Генерирует число заданной длиныlength, склеивая случайные цифры. -
randrange(start, stop=None, step=1)Полный аналог стандартногоrange— возвращает элемент изrange(start, stop, step). Верхняя граница не включается. Можно указывать один агрумент. -
random_integer(start, end, step=1)(алиас:randint) Возвращает случайное целое числоN, такое чтоstart <= N <= end(обе границы включены).step: Шаг генерации. Например,step=2вернет только чётные (или нечётные) числа. Необязательный аргумент.
🧩 Примеры 2
from pycustomrand import gen_random_number, randrange, random_integer
print(gen_random_number(5)) # Случайное число длиной 5, например: 92103
print(randrange(10)) # Случайное число из диапазона [0, 10)
print(randrange(1, 10)) # Случайное число из диапазона [1, 10)
print(randrange(0, 10, 2)) # Случайное чётное число из диапазона [0, 10)
print(random_integer(1, 10)) # Случайное целое число из диапазона [1, 10]
print(random_integer(0, 10, 2)) # Случайное чётное целое число из диапазона [0, 10]
# randint - алиас для random_integer, работает при "import pycustomrand", "from pycustomrand import *" или "from pycustomrand import randint"
# randint(1, 10) равноценно random_integer(1, 10)-
random()Возвращает случайное числоfloatв диапазоне[0.0, 1.0). -
random_float(start, end, digits=None)Возвращает числоfloatв диапазоне[start, end)или[start, end]в зависимости от округления (при наличииdigits).start,end: Начало и конец диапазона, могут быть как целыми числами, так и числами с плавающей точкой.digits: Если число указано, результат будет округлён до этого количества знаков с помощьюtrue_round.
🧩 Примеры 3
from pycustomrand import random, random_float
print(random()) # Случайное число в диапазоне [0, 1), например 0.2260351121787103
print(random_float(0, 10)) # Случайное число с плавающей точкой в диапазоне [0, 10), например 4.014874483651235
print(random_float(0, 10, digits=3)) # То же самое, только с округлением до 3-ёх знаков, например 6.722-
choice(array)Возвращает один случайный элемент из последовательности. -
choices(array, k, weights=None)Возвращает список изkслучайных элементов с возможностью повторений.weights: Список весов (вероятностей) для каждого элемента (соответствует по индексу). ЕслиNone— все элементы считаются равными по весу.
-
shuffle(array)Перемешивает изменяемую последовательность (список) на месте (in-place). -
sample(array, k, counts=None)Возвращает список изkуникальных случайных элементов.counts: Список с количеством повторений для каждого элемента массива (соответствует по индексу).
🧩 Примеры 4
from pycustomrand import choice, choices, shuffle, sample
array = ["apple", "banana", "cherry", "orange"]
print(choice(array)) # Случайный элемент из массива, например "cherry"
print(choices(array, k=2)) # Список из k случайных элементов из массива, например ['apple', 'cherry']
print(choices(array, k=2, weights=[1, 2, 3, 4])) # Список из k случайных элементов из массива с весами, например ['orange', 'banana']
# "orange" (с весом 4) будет выпдать в четыре раза чаще, чем "apple" (с весом 1)
shuffle(array) # Перемешивает массив на месте
print(array) # Например ['cherry', 'banana', 'apple', 'orange']
print(sample(array, k=2)) # Список из k уникальных случайных элементов из массива, например ['cherry', 'apple']
print(sample(array, k=2, counts=[1, 2, 3, 4])) # Список из k уникальных случайных элементов из массива с весами, например ['banana', 'orange']
# "orange" (с количеством в массиве 4) будет выпдать в четыре раза больше, чем "apple" (количество в массиве 1)Эти функции используются для моделирования реальных процессов (физика, экономика, игры).
-
triangular(low=0.0, high=1.0, mode=None)— Треугольное распределение. Генерирует число в диапазоне[low, high], но чаще всего выпадает числоmode(вершина треугольника). Используется в простом моделировании и играх. Пример: Урон мечом от 5 до 15, но чаще всего бьёт на 10 —triangular(5, 15, 10). -
gauss(mu=0.0, sigma=1.0)— Нормальное распределение (Колокол Гаусса). Большинство значений группируется вокруг среднего (mu), аsigma(стандартное отклонение) показывает разброс. Используется для моделирования природных явлений. Примеры: Рост людей, IQ, ошибки измерений, разброс пуль при стрельбе).mu: Среднее значение (центр).sigma: Стандартное отклонение (разброс).
-
expovariate(lambd=1.0)— Экспоненциальное распределение. Описывает время между событиями в процессе Пуассона. Часто выпадают маленькие значения, редко — большие (длинный хвост). Используется в таймерах. Примеры: Время между приходом автобусов. В игре спавн монстров — обычно они лезут часто, но иногда случаются долгие затишья.lambd: Интенсивность событий (должна быть > 0).
-
binomialvariate(n=1, p=0.5)— Биномиальное распределение (алиас:binomial). Количество успехов в серии изnнезависимых испытаний с вероятностью успехаp. Используется в моделировании финансов и математике. Примеры: Сколько раз сейчас выпадет орёл, если подбросить монету 10 раз —binomialvariate(n=10, p=0.5).
🧩 Примеры 5
from pycustomrand import triangular, gauss, expovariate, binomialvariate
print(triangular(low=0.0, high=1.0, mode=0.5)) # Случайное число с плавающей точкой из треугольного распределения (диапазон [0.0, 1.0])
# Чаще всего выпадает значение ±0.5, например: 0.6508330793068139
print(gauss(mu=0.0, sigma=1.0)) # Случайное число с плавающей точкой из нормального "колокольного" распределения (общий диапазон 0.0 ± ~3.0)
# Чаще всего выпадает значение 0.0 ± 1.0, например: 1.0665809173007805 или -1.650128903962443
print(expovariate(lambd=1.0)) # Случайное число с плавающей точкой из экспоненциального распределения (общий диапазон 0.0 ± ~4.0)
# Чаще всего выпадает наименьшее значение от 0.0 до 1.0, например: 0.405175514533143
print(binomialvariate(n=10, p=0.5)) # Случайное число из биномиального распределения (диапазон [0, 10]), например: 5
# Чем меньше вероятность p - тем чаще будет выпадать число из первой половины диапазона [0, 10], больше - большее из второй половины
# binomial - алиас для binomialvariate, работает при "import pycustomrand", "from pycustomrand import *" или "from pycustomrand import binomial"
# binomial(n=10, p=0.5)) равноценно binomialvariate(n=10, p=0.5)-
random_bytes(count): Генерация случайных байт в количествеcount. -
random_uuid4(): Генерация уникального идентификатора (UUID v4). -
random_color_hex(): Случайный цвет в формате HEX. -
random_bool(true_chance=0.5): Возвращает True или False c вероятностьюtrue_chance.
🧩 Примеры 6
from pycustomrand import random_bytes, random_uuid4, random_color_hex, random_bool
print(random_bytes(10)) # Случайные 10 байтов, например: b'\x8b\x91\x19\xe42\xcd\x80\x82b\xba'
print(random_uuid4()) # Случайный UUID v4, например: '0e1d2eeb-1627-4cfa-8130-afe74e1c5ce9'
print(random_color_hex()) # Cлучайный цвет в формате hex, например: '#0ca3e7'
print(random_bool()) # Случайное значение True/False, например: TrueМодуль решает проблему "банковского округления" в Python 3, где round(x.5) округляется до ближайшего чётного числа.
true_round использует честное математическое округление (отсюда и название "true" — истинное/честное).
Для удобства модуль может быть импортирован напрямую из пакета (from pycustomrand import true_round).
| Число | Стандартный round() |
PyCustomRand true_round() |
Примечание |
|---|---|---|---|
| 2.5 | 2 | 3 | Математическое округление (0.5 → вверх) |
| 3.5 | 4 | 4 | Совпадает |
| 2.675 (до 2-ух знаков) | 2.67 | 2.68 | Исправление погрешности Floating Point Error |
| 1.005 (до 2-ух знаков) | 1.0 | 1.01 | Корректная обработка граничных значений |
| 0.00049 (до 3-ёх знаков) | 0.0 | 0.001 | Точность при работе с малыми числами |
Проект имеет следующую файловую структуру:
PyCustomRand/ # Корень репозитория
├── .github/
│ └── workflows/
│ └── python-app.yml # Конфигурация GitHub Actions: автоматический запуск тестов при каждом Push/PR
│
├── pycustomrand/ # Исходный код пакета
│ ├── __init__.py # Точка входа: инициализация пакета и алиасы функций
│ ├── custom_round.py # Реализация алгоритма математического округления (true_round)
│ ├── diagnostics.py # Декоратор для проверки равномерности распределения чисел
│ └── random_generator.py # Ядро библиотеки: класс PseudoRandom и вся логика генерации
│
├── tests/ # Набор Unit-тестов
│ ├── __init__.py # Пустой файл (чтобы тесты видели друг друга)
│ ├── test_random.py # Тесты для генератора, seed, диапазонов и утилит
│ └── test_round.py # Тесты для проверки корректности округления
│
├── .gitignore # Правила исключения файлов из Git (venv, кэш, логи)
├── LICENSE # Текст лицензии MIT
├── pyproject.toml # Конфигурационный файл сборки пакета для PyPI
└── README.md # Документация проекта
Приветствуется любая помощь в развитии библиотеки. Если у вас есть идеи по улучшению алгоритмов, оптимизации кода или вы нашли ошибку — смело создавайте Issue/Pull Request.
Как внести свой вклад:
- Сделайте Fork репозитория;
- Создайте новую ветку для вашей фичи (
git checkout -b feature/SomeFeature); - Внесите изменения;
- Запустите тесты, чтобы убедиться, что ваши изменения ничего не сломали:
python -m unittest discover tests
- Запушьте изменения (
git push origin feature/SomeFeature); - Откройте Pull Request.
Этот проект является программным обеспечением с открытым исходным кодом и распространяется под лицензией MIT License.
Copyright © 2025 Ivan (n1xsi)
Данная лицензия разрешает любому лицу получать копию данного программного обеспечения и сопутствующей документации бесплатно,
использовать его без ограничений, включая право копировать, модифицировать, публиковать и распространять копии ПО.
Полный текст лицензии доступен в файле LICENSE.


