Patvirtinkite ir generuokite numerius naudodami Luhno algoritmą, dažnai naudojamą kreditinių kortelių numeriams, Kanados socialinio draudimo numeriams ir kitiems identifikavimo numeriams. Patikrinkite, ar numeris atitinka Luhno patikrinimą, arba generuokite galiojančius numerius, kurie atitinka algoritmą.
Luhn algoritmas, dar žinomas kaip "modulio 10" arba "mod 10" algoritmas, yra paprasta kontrolinė suma, naudojama įvairių identifikavimo numerių, tokių kaip kreditinių kortelių numeriai, Kanados socialinio draudimo numeriai, IMEI numeriai ir nacionaliniai teikėjų identifikavimo numeriai JAV, patvirtinimui. Ši skaičiuoklė leidžia jums patvirtinti numerius naudojant Luhn algoritmą ir generuoti galiojančius numerius, kurie praeina Luhn patikrinimą.
Luhn algoritmas veikia taip:
Štai vizualinė Luhn algoritmo atvaizdavimo schema:
Luhn algoritmas gali būti išreikštas matematiškai taip:
Tegu yra -asis skaitmuo, skaičiuojant nuo dešiniojo skaitmens (neįskaitant kontrolinio skaitmens) ir judant į kairę. Tada kontrolinis skaitmuo pasirenkamas taip, kad:
Kur yra modulo operacija.
Luhn algoritmas turi įvairių taikymo sričių skirtingose srityse:
Nors Luhn algoritmas yra plačiai naudojamas, yra ir kitų kontrolinių sumų algoritmų skirtingiems tikslams:
Luhn algoritmą sukūrė Hans Peter Luhn, IBM kompiuterių mokslininkas, 1954 metais. Luhn buvo informacijos mokslo pionierius ir jam priskiriama daugybė inovacijų, įskaitant KWIC (Key Word In Context) indeksavimo sistemą.
Algoritmas iš pradžių buvo sukurtas apsaugoti nuo atsitiktinių klaidų, o ne nuo piktybinių atakų. Svarbu pažymėti, kad nors Luhn algoritmas gali aptikti daugelį įprastų klaidų, jis nėra saugi šifravimo forma ir neturėtų būti naudojamas duomenų saugumo tikslais.
Nepaisant savo amžiaus, Luhn algoritmas išlieka plačiai naudojamas dėl savo paprastumo ir efektyvumo, aptinkant įprastas rašymo klaidas.
Štai keletas kodo pavyzdžių, kaip įgyvendinti Luhn algoritmą įvairiose programavimo kalbose:
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## Pavyzdžio naudojimas:
22print(luhn_validate(4532015112830366)) # True
23print(luhn_validate(4532015112830367)) # False
24print(generate_valid_number(16)) # Generuoja galiojantį 16 skaitmenų numerį
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// Pavyzdžio naudojimas:
29console.log(luhnValidate(4532015112830366)); // true
30console.log(luhnValidate(4532015112830367)); // false
31console.log(generateValidNumber(16)); // Generuoja galiojantį 16 skaitmenų numerį
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)); // Generuoja galiojantį 16 skaitmenų numerį
47 }
48}
49
Įgyvendinant Luhn algoritmą, atsižvelkite į šiuos kraštutinius atvejus ir specialius svarstymus:
Įvesties patikrinimas: Užtikrinkite, kad įvestis būtų galiojantis numerio simbolių rinkinys. Ne skaitmeniniai simboliai turėtų būti tinkamai apdoroti (arba pašalinti, arba laikomi negaliojančia įvestimi).
Pirmieji nuliai: Algoritmas turėtų teisingai veikti su numeriais, turinčiais pirmuosius nulius.
Dideli numeriai: Būkite pasiruošę tvarkyti labai ilgus numerius, kurie gali viršyti standartinių sveikųjų skaičių tipų talpą kai kuriose programavimo kalbose.
Tuščia įvestis: Apibrėžkite, kaip jūsų įgyvendinimas turėtų tvarkyti tuščius simbolių rinkinius arba null įvestis.
Ne standartiniai simbolių rinkiniai: Kai kuriose programose galite susidurti su numeriais, kurie yra atvaizduojami simboliais už standartinio 0-9 intervalo. Apibrėžkite, kaip šie turėtų būti tvarkomi.
Veiklos svarstymai: Programoms, kurioms reikia greitai patvirtinti didelį skaičių įvesties, apsvarstykite algoritmo įgyvendinimo optimizavimą.
Galiojantis kreditinės kortelės numeris:
Negaliojantis kreditinės kortelės numeris:
Galiojantis Kanados socialinio draudimo numeris:
Negaliojantis IMEI numeris:
Norėdami patvirtinti Luhn algoritmo įgyvendinimą, galite naudoti šiuos testavimo atvejus:
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 # Testuokite generuotus numerius
8 for _ in range(10):
9 assert luhn_validate(generate_valid_number(16)) == True
10
11 print("Visi testai praėjo!")
12
13test_luhn_algorithm()
14