Ověřte a generujte čísla pomocí Luhnova algoritmu, který se běžně používá pro čísla kreditních karet, kanadská čísla sociálního pojištění a další identifikační čísla. Otestujte, zda číslo projde Luhnovým testem, nebo generujte platná čísla, která vyhovují tomuto algoritmu.
Luhnův algoritmus, také známý jako algoritmus "modulus 10" nebo "mod 10", je jednoduchý kontrolní součet, který se používá k validaci různých identifikačních čísel, jako jsou čísla kreditních karet, kanadská čísla sociálního pojištění, IMEI čísla a čísla národního poskytovatele v USA. Tento kalkulátor vám umožňuje validovat čísla pomocí Luhnova algoritmu a generovat platná čísla, která projdou Luhnovou kontrolou.
Luhnův algoritmus funguje následovně:
Zde je vizuální znázornění Luhnova algoritmu:
Luhnův algoritmus lze matematicky vyjádřit takto:
Nechť je -tá číslice, počítáno od pravé nejvíce číslice (s výjimkou kontrolní číslice) a pohybující se vlevo. Potom je kontrolní číslice vybrána tak, aby:
Kde je modulo operace.
Luhnův algoritmus má různé aplikace v různých oblastech:
I když je Luhnův algoritmus široce používán, existují i jiné algoritmy kontrolního součtu pro různé účely:
Luhnův algoritmus vytvořil Hans Peter Luhn, počítačový vědec z IBM, v roce 1954. Luhn byl průkopníkem v oblasti informační vědy a je přičítán několika inovacím, včetně systému indexování KWIC (Key Word In Context).
Algoritmus byl původně navržen k ochraně proti náhodným chybám, nikoli proti zlým útokům. Je důležité poznamenat, že i když Luhnův algoritmus může detekovat mnoho běžných chyb, není bezpečnou formou šifrování a neměl by být spolehlivě používán pro účely zabezpečení dat.
Navzdory svému věku zůstává Luhnův algoritmus široce používán díky své jednoduchosti a účinnosti při zachycování běžných chyb při přepisu.
Zde jsou některé příklady kódu pro implementaci Luhnova algoritmu v různých programovacích jazycích:
1import random
2
3def luhn_validate(number):
4 digits = [int(d) for d in str(number)]
5 checksum = 0
6 for i in range(len(digits) - 1, -1, -1):
7 d = digits[i]
8 if (len(digits) - i) % 2 == 0:
9 d = d * 2
10 if d > 9:
11 d -= 9
12 checksum += d
13 return checksum % 10 == 0
14
15def generate_valid_number(length):
16 digits = [random.randint(0, 9) for _ in range(length - 1)]
17 checksum = sum(digits[::2]) + sum(sum(divmod(d * 2, 10)) for d in digits[-2::-2])
18 check_digit = (10 - (checksum % 10)) % 10
19 return int(''.join(map(str, digits + [check_digit])))
20
21## Příklad použití:
22print(luhn_validate(4532015112830366)) # True
23print(luhn_validate(4532015112830367)) # False
24print(generate_valid_number(16)) # Generuje platné 16-ciferné číslo
25
1function luhnValidate(number) {
2 const digits = number.toString().split('').map(Number);
3 let checksum = 0;
4 for (let i = digits.length - 1; i >= 0; i--) {
5 let d = digits[i];
6 if ((digits.length - i) % 2 === 0) {
7 d *= 2;
8 if (d > 9) d -= 9;
9 }
10 checksum += d;
11 }
12 return checksum % 10 === 0;
13}
14
15function generateValidNumber(length) {
16 const digits = Array.from({length: length - 1}, () => Math.floor(Math.random() * 10));
17 const checksum = digits.reduce((sum, digit, index) => {
18 if ((length - 1 - index) % 2 === 0) {
19 digit *= 2;
20 if (digit > 9) digit -= 9;
21 }
22 return sum + digit;
23 }, 0);
24 const checkDigit = (10 - (checksum % 10)) % 10;
25 return parseInt(digits.join('') + checkDigit);
26}
27
28// Příklad použití:
29console.log(luhnValidate(4532015112830366)); // true
30console.log(luhnValidate(4532015112830367)); // false
31console.log(generateValidNumber(16)); // Generuje platné 16-ciferné číslo
32
1import java.util.Random;
2
3public class LuhnValidator {
4 public static boolean luhnValidate(long number) {
5 String digits = String.valueOf(number);
6 int checksum = 0;
7 boolean isEven = true;
8 for (int i = digits.length() - 1; i >= 0; i--) {
9 int digit = Character.getNumericValue(digits.charAt(i));
10 if (isEven) {
11 digit *= 2;
12 if (digit > 9) digit -= 9;
13 }
14 checksum += digit;
15 isEven = !isEven;
16 }
17 return checksum % 10 == 0;
18 }
19
20 public static long generateValidNumber(int length) {
21 Random random = new Random();
22 long[] digits = new long[length - 1];
23 for (int i = 0; i < length - 1; i++) {
24 digits[i] = random.nextInt(10);
25 }
26 long checksum = 0;
27 for (int i = digits.length - 1; i >= 0; i--) {
28 long digit = digits[i];
29 if ((length - 1 - i) % 2 == 0) {
30 digit *= 2;
31 if (digit > 9) digit -= 9;
32 }
33 checksum += digit;
34 }
35 long checkDigit = (10 - (checksum % 10)) % 10;
36 long result = 0;
37 for (long digit : digits) {
38 result = result * 10 + digit;
39 }
40 return result * 10 + checkDigit;
41 }
42
43 public static void main(String[] args) {
44 System.out.println(luhnValidate(4532015112830366L)); // true
45 System.out.println(luhnValidate(4532015112830367L)); // false
46 System.out.println(generateValidNumber(16)); // Generuje platné 16-ciferné číslo
47 }
48}
49
Při implementaci Luhnova algoritmu zvažte následující okrajové případy a zvláštní úvahy:
Validace vstupu: Zajistěte, aby byl vstup platným číselným řetězcem. Nečíselné znaky by měly být zpracovány vhodně (buď odstraněny, nebo považovány za neplatný vstup).
Počáteční nuly: Algoritmus by měl správně fungovat s čísly, která mají počáteční nuly.
Velká čísla: Buďte připraveni zpracovat velmi dlouhá čísla, která mohou překročit kapacitu standardních celočíselných typů v některých programovacích jazycích.
Prázdný vstup: Definujte, jak by vaše implementace měla zpracovat prázdné řetězce nebo null vstupy.
Nestandardní znakové sady: V některých aplikacích můžete narazit na čísla reprezentovaná znaky mimo standardní rozsah 0-9. Definujte, jak by měla být tato čísla zpracována.
Úvahy o výkonu: Pro aplikace, které potřebují rychle validovat velké množství vstupů, zvažte optimalizaci implementace algoritmu.
Platné číslo kreditní karty:
Neplatné číslo kreditní karty:
Platné kanadské číslo sociálního pojištění:
Neplatné číslo IMEI:
Pro ověření implementace Luhnova algoritmu můžete použít následující testovací případy:
1def test_luhn_algorithm():
2 assert luhn_validate(4532015112830366) == True
3 assert luhn_validate(4532015112830367) == False
4 assert luhn_validate(79927398713) == True
5 assert luhn_validate(79927398714) == False
6
7 # Test generovaných čísel
8 for _ in range(10):
9 assert luhn_validate(generate_valid_number(16)) == True
10
11 print("Všechny testy prošly!")
12
13test_luhn_algorithm()
14