суббота, 3 ноября 2012 г.

Как создать генератор номера счёта? (Перевод)

Требования к генератору:
  1. Выдача псевдо-случайных последовательных номеров (уникальных для десятков миллионов записей)
  2. Простая проверка корректности (без обращения к БД)
Мы будем использовать сеть Фейстеля для создания псевдо-случайных чисел (только положительных) из последовательных чисел (т.е. возвращаемых при помощи nextval() для posgresql sequence). Этот алгоритм принимает базис для функции `make_feistel_number`, доступной в пакете wheezy.core.
Настройка окружения перед началом работы:
$ virtualenv env
$ env/bin/easy_install wheezy.core
$ env/bin/python
Давайте немного поиграем с генерацией чисел (обратите внимание, что функция обратима и последовательна, все числа уникальны, без повторений):
>>> from wheezy.core.feistel import make_feistel_number
>>> from wheezy.core.feistel import sample_f
>>> feistel_number = make_feistel_number(sample_f)
>>> feistel_number(1)
573852158
>>> feistel_number(2)
1788827948
>>> feistel_number(1788827948)
2
Мы будем использовать алгоритм Луна для создания контрольной цифры. Этот алгоритм доступен в пакете wheezy.core.
>>> from wheezy.core.luhn import luhn_checksum
>>> luhn_checksum(123456789)
7
Есть так же полезная функция для проверки корректности полученного числа при помощи этой контрольной цифры:
>>> from wheezy.core.luhn import luhn_sign
>>> from wheezy.core.luhn import is_luhn_valid
>>> luhn_sign(123456789)
1234567897
>>> is_luhn_valid(1234567897)
True
>>> is_luhn_valid(34518893)
False
Теперь давайте сделаем красивый номер счёта (с нулями для доведения до нужного количества цифр, префиксом и т.д.):
>>> account_number = lambda n: 'Z%011d' % luhn_sign(feistel_number(n))
>>> account_number(1)
'Z05738521581'
>>> account_number(2)
'Z17888279480'
>>> account_number(3)
'Z07395350007'
Да, этот алгоритм оптимизирован для скорости и потому Вы должны предоставить свою собственную реализацию `sample_f` для обеспечения безопасности. Код доступен здесь.

Источник

Комментариев нет:

Отправить комментарий