Продавцы воздуха поговаривают, что этим алгоритмом можно проверить картон. Докажу обратное:
Например нам нужно сгенерировать "валидный" номер карты QIWI BANK, для этого мы берём BIN банка QIWI - 469395
В стандартной карте 16 цифр, из которых первые 6 - это BIN (Bank Identification Number), остальные 9 цифр указываю на аккаунт и/или другую информацию для банка, а последняя 10ая цифра, это и есть CHECK, который считается по специальному алгоритму Луна (Luhn)
Берём 6 цифр нужного нам банка, 469395 добавляем к ним 9 цифр похожие на что-то настоящее, 713877391 и получаем код из 15 цифр - 469395 713877391 (отделил пробелом для наглядности)
4693 9571 3877 391* - вот наша карта, не хватает последней "чековой" цифры, её мы посчитаем согласно алгоритму Luhn
Начнём считать нашу "звездочку" (checksum), "% 10" в примере означает деление с остатком на 10
checksum = 10 - ((luhn(num1) + num2 + luhn(num3) + num4 + luhn(num5) + num6 + luhn(num7) + num8 + luhn(num9) + num10 + luhn(num11) + num12 + luhn(num13) + num14 + luhn(num15)) % 10)
Теперь поясню, что делает операция luhn(const), константа умножается на 2 и если она становится больше/равна 10ти, то отнимается 9, а иначе ничего не делаем, так и оставляем
Эту операцию мы проделываем с 1, 3, 5, 7, 9, 11, 13, 15 (нечётными) цифрами в нашем сгенерированном номере
checksum = 10 - ((luhn(4)+6+luhn(9)+3+luhn(9)+5+luhn(7)+1+luhn(3)+ 8+luhn(7)+7+luhn(3)+9+luhn(1)) % 10)
4*2 = 8, где 8<10, значит оставляем 8,
9*2 = 18, где 18>10, значит отнимаем 9 и получаем 9
9*2, аналогично, 9
7*2 = 14, снова больше 10, значит 14-9=5
3*2 = 6, оставляем 6
7*2, аналогично 5
3*2, аналогично, что и было ранее, это 6
1*2 = 2, так и оставляем 2
Теперь видим вот какой результат после преобразования:
checksum = 10 - ((8+6+9+3+9+5+5+1+6+8+5+7+6+9+2 % 10)
Получим в сумме 89, которую поделим на 10 с остатком, результат 9, а потом эту 9ку отнимем от 10ки и получим 1
Или просто наглядно посмотрим, сколько нужно добавить к 89, чтобы было кратное 10ти число? 89+1=90, всё, теперь кратное
checksum = 1
4693 9571 3877 3911 - вот и стала ясна последняя цифра для того, чтобы наш сгенерированный номер был "валидным"
Код программы на языке python (для проверки номера по алгоритму Luhn):
#coding: utf8
cvv = raw_input('
33[1;32mВведите номер карты (16 цифр):33[1;m
')
if len(cvv) == 16 and cvv.isdigit():
def da©:
c = int©
c *= 2
if c >= 10:
c -= 9
return c
if (da(cvv[0]) + int(cvv[1]) + da(cvv[2]) + int(cvv[3]) + da(cvv[4]) + int(cvv[5]) + da(cvv[6]) + int(cvv[7]) + da(cvv[8]) + int(cvv[9]) + da(cvv[10]) + int(cvv[11]) + da(cvv[12]) + int(cvv[13]) + da(cvv[14]) + int(cvv[15])) % 10 == 0:
print "
33[1;37mVALID33[1;m"
bankidnum = cvv[0] + cvv[1] + cvv[2] + cvv[3] + cvv[4] + cvv[5]
print "
33[1;37mbin =33[1;m",bankidnum
account = cvv[6] + cvv[7] + cvv[8] + cvv[9] + cvv[10] + cvv[11] + cvv[12] + cvv[13] + cvv[14]
print "33[1;37maccount =33[1;m",account
checksum = 10 - ((da(cvv[0]) + int(cvv[1]) + da(cvv[2]) + int(cvv[3]) + da(cvv[4]) + int(cvv[5]) + da(cvv[6]) + int(cvv[7]) + da(cvv[8]) + int(cvv[9]) + da(cvv[10]) + int(cvv[11]) + da(cvv[12]) + int(cvv[13]) + da(cvv[14])) % 10)
if checksum != 10:
print "33[1;37mchecksum =33[1;m",checksum,"
"
else:
checksum = 0
print "33[1;37mchecksum =33[1;m",checksum,"
"
else:
print "
33[1;30mNOT VALID33[1;m
"
elif len(cvv) == 0:
print "
33[1;30mВы ничего не ввели33[1;m
"
elif not cvv.isdigit():
print "
33[1;30mПопробуйте ввести только цифры33[1;m
"
elif cvv.isdigit() and len(cvv) < 16:
print "
33[1;30mНедостаточно цифр33[1;m
"
elif cvv.isdigit() and len(cvv) > 16:
print "
33[1;30mСлишком много цифр33[1;m
"