Wpisany przez Tomasz Lubiński,
11 kwietnia 2007 19:42
Algorytm Verhoeff'a, który służy do obliczania sumy kontrolnej został po raz pierwszy opublikowany w 1969. Jego nazwa pochodzi od twórcy - holenderskiego matematyka Jacobus'a Verhoeff'a. Opracowana przez niego metoda jest doskonalsza od przedstawionego algorytmu Luhn'a i pozwala na wykrycie:
Algorytm pozwala zabezpieczyć ciąg cyfr dowolnej długości. Numery używające tej metody mają następującą strukturę XXXXXXXC, gdzie XXXXXXX to numer identyfikacyjny (o dowolnej liczbie cyfr), a C to cyfra kontrolna. Algorytm bazuje na właśnościach grupy dihedralnej D5. W praktyce wykorzystuje się 3 tablice z gotowymi wartościami:
Pierwsza tablica d zawiera wartości mnożenia w grupie dihedrealnej D5.
Kolejna tablica p zawiera permutację dla każdej cyfry, bazujące na jej pozycji w sprawdzanym identyfikatorze. Pozycje w numerze zabezpieczonym tą metodą liczone są od prawej do lewej począwszy od zera. Permutacje powtarzają się po ósmym wierszu, czyli permutacja dla pozycji 8 jest taka sama jak dla pozycji 0, dla 9 taka jak dla 1, itd...
Trzecia tablica inv przedstawia element odwrotny mnożenia w grupie D5 przedstawionego w pierwszej tabeli, czyli taki że: d(i, inv(i)) = 0. Tablica ta nie jest używana do sprawdzania czy dany identyfikator jest prawidłowy a jedynie do wyznaczenia cyfry kontrolnej dla zadanego numeru.
Sprawdzanie poprawności numeru jest bardzo proste - kolejne cyfry numeru identyfikacyjnego oznaczymy przez ni, gdzie i jest pozycją cyfry w identyfikatorze licząc od 0 od prawej strony. Zatem n0 to cyfra kontrolna.
Sprawdzimy czy identyfikator 8107 jest prawidłowy.
Inicjujemy c = 0 i przystępujemy do obliczeń.
c = d(c, p(i mod 8, ni))
c = d(0, p(0 mod 8, 7)) = d(0, 7) = 7
c = d(7, p(1 mod 8, 0)) = d(7, 1) = 6
c = d(6, p(2 mod 8, 1)) = d(6, 8) = 3
c = d(3, p(3 mod 8, 8)) = d(3, 2) = 0
c = 0. Zatem identyfikator 8107 jest prawidłowy.
A co w sytuacji, gdy mamy identyfikator i chcemy obliczyć cyfrę kontrolną? Tutaj schemat postępowania jest również dosyć prosty - tak jak poprzednio kolejne cyfry numeru identyfikacyjnego oznaczymy przez ni, gdzie i jest pozycją cyfry w identyfikatorze licząc od 0 od prawej strony. Zatem n0 to cyfra kontrolna.:
Obliczymy cyfrę kontrolną dla identyfikatora 123c.
Na początku inicjujemy cyfrę kontrolną zerem, zatem otrzymujemy 1230.
Inicjujemy c = 0 i przystępujemy do obliczeń.
c = d(c, p(i mod 8, ni))
c = d(0, p(0 mod 8, 0)) = d(0, 0) = 0
c = d(0, p(1 mod 8, 3)) = d(0, 6) = 6
c = d(6, p(2 mod 8, 2)) = d(6, 0) = 6
c = d(6, p(3 mod 8, 1)) = d(6, 9) = 2
wartość cyfry kontrolnej n0 = inv(c) = inv(2) = 3.
Zatem poprawny identyfikator z cyfrą kontrolną to 1233.
- wszystkich błędów na jednym znaku,
- wszystkich błędów zamiany kolejności dwóch znaków, np: 09 -> 90 i na odwrót,
- większość podwójnych błędów, np: 22 -> 33,
- większość podwójnych błędów oddzielonych znakiem, np: 494 -> 191,
- większość zmian kolejności trzech znaków , np: 123 -> 321,
- większość tzw. błędów fonetycznych dla języka angielskiego, np: "sixty" -> "sixteen" 60 -> 16.
Algorytm pozwala zabezpieczyć ciąg cyfr dowolnej długości. Numery używające tej metody mają następującą strukturę XXXXXXXC, gdzie XXXXXXX to numer identyfikacyjny (o dowolnej liczbie cyfr), a C to cyfra kontrolna. Algorytm bazuje na właśnościach grupy dihedralnej D5. W praktyce wykorzystuje się 3 tablice z gotowymi wartościami:
Pierwsza tablica d zawiera wartości mnożenia w grupie dihedrealnej D5.
d | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
0 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
1 | 1 | 2 | 3 | 4 | 0 | 6 | 7 | 8 | 9 | 5 |
2 | 2 | 3 | 4 | 0 | 1 | 7 | 8 | 9 | 5 | 6 |
3 | 3 | 4 | 0 | 1 | 2 | 8 | 9 | 5 | 6 | 7 |
4 | 4 | 0 | 1 | 2 | 3 | 9 | 5 | 6 | 7 | 8 |
5 | 5 | 9 | 8 | 7 | 6 | 0 | 4 | 3 | 2 | 1 |
6 | 6 | 5 | 9 | 8 | 7 | 1 | 0 | 4 | 3 | 2 |
7 | 7 | 6 | 5 | 9 | 8 | 2 | 1 | 0 | 4 | 3 |
8 | 8 | 7 | 6 | 5 | 9 | 3 | 2 | 1 | 0 | 4 |
9 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
Kolejna tablica p zawiera permutację dla każdej cyfry, bazujące na jej pozycji w sprawdzanym identyfikatorze. Pozycje w numerze zabezpieczonym tą metodą liczone są od prawej do lewej począwszy od zera. Permutacje powtarzają się po ósmym wierszu, czyli permutacja dla pozycji 8 jest taka sama jak dla pozycji 0, dla 9 taka jak dla 1, itd...
p | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
0 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
1 | 1 | 5 | 7 | 6 | 2 | 8 | 3 | 0 | 9 | 4 |
2 | 5 | 8 | 0 | 3 | 7 | 9 | 6 | 1 | 4 | 2 |
3 | 8 | 9 | 1 | 6 | 0 | 4 | 3 | 5 | 2 | 7 |
4 | 9 | 4 | 5 | 3 | 1 | 2 | 6 | 8 | 7 | 0 |
5 | 4 | 2 | 8 | 6 | 5 | 7 | 3 | 9 | 0 | 1 |
6 | 2 | 7 | 9 | 3 | 8 | 0 | 6 | 4 | 1 | 5 |
7 | 7 | 0 | 4 | 6 | 9 | 1 | 3 | 2 | 5 | 8 |
Trzecia tablica inv przedstawia element odwrotny mnożenia w grupie D5 przedstawionego w pierwszej tabeli, czyli taki że: d(i, inv(i)) = 0. Tablica ta nie jest używana do sprawdzania czy dany identyfikator jest prawidłowy a jedynie do wyznaczenia cyfry kontrolnej dla zadanego numeru.
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
0 | 4 | 3 | 2 | 1 | 5 | 6 | 7 | 8 | 9 |
Sprawdzanie poprawności numeru jest bardzo proste - kolejne cyfry numeru identyfikacyjnego oznaczymy przez ni, gdzie i jest pozycją cyfry w identyfikatorze licząc od 0 od prawej strony. Zatem n0 to cyfra kontrolna.
- inicjujemy zmienną pomocniczą c = 0
- dla kolejnych cyfr od prawej do lewej strony obliczamy korzystając z podanych wcześniej tablic:
c = d(c, p(i mod 8, ni)) - jeżeli po wykonaniu obliczeń dla wszystkich cyfr c = 0, to podany identyfikator jest prawidłowy
Przykład:
Sprawdzimy czy identyfikator 8107 jest prawidłowy.
Inicjujemy c = 0 i przystępujemy do obliczeń.
c = d(c, p(i mod 8, ni))
c = d(0, p(0 mod 8, 7)) = d(0, 7) = 7
c = d(7, p(1 mod 8, 0)) = d(7, 1) = 6
c = d(6, p(2 mod 8, 1)) = d(6, 8) = 3
c = d(3, p(3 mod 8, 8)) = d(3, 2) = 0
c = 0. Zatem identyfikator 8107 jest prawidłowy.
A co w sytuacji, gdy mamy identyfikator i chcemy obliczyć cyfrę kontrolną? Tutaj schemat postępowania jest również dosyć prosty - tak jak poprzednio kolejne cyfry numeru identyfikacyjnego oznaczymy przez ni, gdzie i jest pozycją cyfry w identyfikatorze licząc od 0 od prawej strony. Zatem n0 to cyfra kontrolna.:
- inicjujemy cyfrę kontrolną, n0 = 0
- inicjujemy zmienną pomocniczą c = 0
- dla kolejnych cyfr od prawej do lewej strony obliczamy korzystając z podanych wcześniej tablic:
c = d(c, p(i mod 8, ni)) - po wykonaniu obliczeń dla wszystkich wstawiamy wartość cyfry kontrolnej n0 = inv(c)
Przykład:
Obliczymy cyfrę kontrolną dla identyfikatora 123c.
Na początku inicjujemy cyfrę kontrolną zerem, zatem otrzymujemy 1230.
Inicjujemy c = 0 i przystępujemy do obliczeń.
c = d(c, p(i mod 8, ni))
c = d(0, p(0 mod 8, 0)) = d(0, 0) = 0
c = d(0, p(1 mod 8, 3)) = d(0, 6) = 6
c = d(6, p(2 mod 8, 2)) = d(6, 0) = 6
c = d(6, p(3 mod 8, 1)) = d(6, 9) = 2
wartość cyfry kontrolnej n0 = inv(c) = inv(2) = 3.
Zatem poprawny identyfikator z cyfrą kontrolną to 1233.
Implementacje
Autor | Język programowania | Komentarz | Otwórz | Pobierz | Ocena |
Tomasz Lubiński | C/C++ | .cpp | .cpp | ***** / 2 | |
Tomasz Lubiński | Delphi/Pascal | .pas | .pas | ***** / 1 | |
Tomasz Lubiński | Java | .java | .java | ***** / 1 |
Poprawiony: 15 sierpnia 2012 07:13