Skip to main content

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

Project description

PyCustomRand

Python Last Commit Run Tests

🌐 Languages: 🇷🇺 Русский | 🇬🇧 English


PyCustomRand — это Python-библиотека для генерации псевдослучайных чисел, основанная на алгоритме, использующем системное время с наносекундной точностью.

Данный авторский проект создан для изучения алгоритмов и альтернативных подходов к генерации случайных чисел и их округлении. Меня не устраивало, что модуль random в Python генерирует недостаточно случайные числа ( особенно при нескольких последовательных генерациях ), а встроенный в Python модуль round довольно "грубо" округляет числа ( round(1.5) = 2 и в то же время round(2.5) = 2 ), поэтому я решил написать свою библиотеку для генерации псевдослучайных чисел — более простую и с наибольшей энтропией.

[!WARNING] PyCustomRand пока не является криптографически стойкой библиотекой и не предназначена для использования в системах безопасности! Используйте secrets модуль.

📌 Зачем нужна эта библиотека, если есть уже встроенные в Python random и round?

PyCustomRand писался как альтернатива этим двум встроенным модулям. Вот главные особенности и возможности библиотеки:

  • Данная библиотека проще написана — весь код закомментирован, лёгок и понятен. В основе реализации генератора псевдослучайных чисел лежит несложный алгоритм, использующий системное время, поэтому библиотеку легко кастомизировать, расширять или дополнять под себя.
  • В большинстве своём PyCustomRand выдаёт более "энтропичный" результат при нескольких генерациях подряд по сравнению со встроенным random-модулем.
    • 📊 Сравнение с диаграммами

      PyCustomRand демонстрирует на 173% более высокую кучность распределения по сравнению со стандартной библиотекой random в тестах на 1.000.000 итераций.

      Данные для диаграммы брались из тестирования, которое проводилось с помощью встроенного модуля диагностики (check_distribution). По результатам PyCustomRand показал максимальное отклонение в 2.7 раза меньше, чем стандартный random (0.0267% против 0.0730%).

      PyCustomRand Python Built-in
      PyCustomRand Python Built-in
  • Библиотека включает в себя все самые главные функции из оригинальной Python-библиотеки, но только местами улучшенные и упрощённые (например: random_integer может выдавать сгенерированный результат, делимый на заданное число из диапазона; результат функции random_float можно округлять и так далее)
    • 📑 Список функций
      • Генерация целых чисел (gen_random_number, randrange, random_integer).
      • Генерация вещественных чисел (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
➕ Альтернативные способы установки Если у вас возникли проблемы с пакетным менеджером Python или прочие ошибки, то PyCustomRand можно установить другими способами:
git clone https://github.com/n1xsi/PyCustomRand.git

📚 Документация

Ниже представлено описание всех доступных функций библиотеки с примерами. Для удобства они могут импороваться напрямую из пакета (from pycustomrand import FUNC_NAME).

1. Управление состоянием (Seeding)

Инициализация генератора позволяет получать воспроизводимые последовательности (например, для тестов или сохранения генерации мира).

  • 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

2. Целые числа

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

3. Вещественные числа

  • 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

4. Последовательности

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

5. Вероятностные распределения

Эти функции используются для моделирования реальных процессов (физика, экономика, игры).

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

6. Утилиты (Extras)

  • 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

🎯 О модуле true_round

Модуль решает проблему "банковского округления" в 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 предоставляет внутренние инструменты для проверки работоспособности библиотеки и качества энтропии генератора случайных чисел.

1. Запуск всех Unit-тестов

Чтобы убедиться, что все функции работают корректно и библиотека установлена правильно, запустите встроенные тесты, находясь в корне репозитория:

python -m unittest discover tests

1.1. Запуск Unit-тестов конкретного модуля

Отдельный запуск проверки модуля генератора случайных чисел:

python -m unittest tests/test_random.py

Отдельный запуск проверки модуля округления чисел:

python -m unittest tests/test_round.py

1.2. Запуск конкретного теста в конкретном модуле

Если вы модифицируете библиотеку, и у вас постоянно не проходит проверку какой-то один конкретный тест, то вы можете не тратить время на запуск всех тестов — вам достаточно запустить один конкретный тест конкретного модуля, например:

from tests.test_round import TestTrueRound
import unittest

# Запуск теста "округления отрицательных чисел" для функции true_round
unittest.main(defaultTest='TestTrueRound.test_negative_numbers')

2. Проверка распределения (Диагностика)

В библиотеку встроен декоратор @check_distribution (находится в pycustomrand.diagnostics). Он позволяет визуально оценить равномерность генерации чисел. Пример использования декоратора:

from pycustomrand.diagnostics import check_distribution
import pycustomrand as pcr

# Декоратор запустит функцию 100.000 раз и разобьёт результаты на 20 корзин
@check_distribution(count=100_000, buckets=20)
def check_float_random():
    return pcr.random()

if __name__ == "__main__":
    check_float_random()

Результат в консоли показывает:

  • На какой сейчас итерации находится диагностика (каждые 5 секунд);
  • Полное время выполнения генерации;
  • Таблицу с количеством попаданий в каждую "корзину" (диапазон);
  • Процентное отклонение от идеального распределения;
  • Вердикт: "Отличное равномерное распределение" или предупреждение о перекосах.
📊 Пример результата диагностики

📂 Структура репозитория

Проект имеет следующую файловую структуру:

PyCustomRand/                # Корень репозитория
├── .github/
│   └── workflows/
│       └── python-app.yml   # Конфигурация GH 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.en.md             # Документация проекта (на Английском)
└── README.md                # Документация проекта (на Русском)

🤝 Вклад в проект (Контрибуция)

Приветствуется любая помощь в развитии библиотеки. Если у вас есть идеи по улучшению алгоритмов, оптимизации кода или вы нашли ошибку — смело создавайте Issue/Pull Request.

Как внести свой вклад:

  1. Сделайте Fork репозитория;
  2. Создайте новую ветку для вашей фичи (git checkout -b feature/SomeFeature);
  3. Внесите изменения;
  4. Запустите тесты, чтобы убедиться, что ваши изменения ничего не сломали:
    python -m unittest discover tests
    
  5. "Запушьте" изменения (git push origin feature/SomeFeature);
  6. Откройте Pull Request.

📄 Лицензия

Этот проект является программным обеспечением с открытым исходным кодом и распространяется под лицензией MIT License.

Copyright © 2025 Ivan (n1xsi)

Данная лицензия разрешает любому лицу получать копию данного программного обеспечения и сопутствующей документации бесплатно,
использовать его без ограничений, включая право копировать, модифицировать, публиковать и распространять копии ПО.

Полный текст лицензии доступен в файле LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pycustomrand-0.0.2.tar.gz (35.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pycustomrand-0.0.2-py3-none-any.whl (19.2 kB view details)

Uploaded Python 3

File details

Details for the file pycustomrand-0.0.2.tar.gz.

File metadata

  • Download URL: pycustomrand-0.0.2.tar.gz
  • Upload date:
  • Size: 35.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for pycustomrand-0.0.2.tar.gz
Algorithm Hash digest
SHA256 4df6abf23d3238ff1399cb1d8dd7d82b0e60a62b8dfc10064529bbf4cf0e860a
MD5 4fc085cae16fedeefa2b76b93676ebe9
BLAKE2b-256 00f4b049362b29197508353fa4658e2ff5ddcfd64ad1f3917afd310bdc92ca2f

See more details on using hashes here.

File details

Details for the file pycustomrand-0.0.2-py3-none-any.whl.

File metadata

  • Download URL: pycustomrand-0.0.2-py3-none-any.whl
  • Upload date:
  • Size: 19.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for pycustomrand-0.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 3bca12d71aedd30a86a0378d5d6271c616e4ed173d99a20e25de3c96731cd1db
MD5 5bb6e3482c89179b241577845523ddd3
BLAKE2b-256 d1e662655134f0cc27a0cdb689837715a31199e199f9fc2944720c117287da4e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page