Blog Dla Młodszych Programistów C#/.NET

29 września 2018
Tagi: JavaScript
Pomyślałem, że dzisiaj może znowu przerobimy jakieś zadanie praktyczne. Na pewno Twoja wiedza jest już wystarczająca aby napisać walidację numerów pesel. Spróbujmy więc napisać funkcję, która będzie sprawdzać czy przekazany do funkcji argument jest prawidłowym numerem pesel.

Aby napisać funkcję, która będzie sprawdzała poprawność numeru pesel, musisz najpierw dowiedzieć się jakie warunki musi sprawdzać podany numer aby był prawidłowym peselem. Zacznijmy więc od teorii. Pesel składa się z ciągu 11 cyfr i nie są to cyfry przypadkowe, każda cyfra ma swoje odpowiednie miejsce. Ostatnia cyfra numeru to cyfra kontrolna, dzięki której będziemy mogli sprawdzać czy numer pesel faktycznie jest prawidłowy. Każda kolejna cyfra ma swoją wagę i są to kolejno wagi: 1, 3, 7, 9, 1, 3, 7, 9, 1, 3, czyli 10 cyfr plus ostatnia 11 czyli cyfra kontrolna. Czyli każdą kolejną cyfrę mnożymy przez jej wagę czyli 1 cyfrę mnożymy przez 1, 2 cyfrę mnożymy przez 3, 3 cyfrę mnożymy 7 itd aż do 10 cyfry. Z otrzymanego wyniki interesuje nas ostatnia cyfra, która jest odejmowana od 10 i jeśli ta cyfra jest zgodna z 11 cyfrą numeru pesel, wtedy pesel jest prawidłowy.

Przykład dla numer pesel - 64042999928.
6*1 + 4*3 + 0*7 + 4*9 + 2*1 + 9*3 + 9*7 + 9*9 + 9*1 + 2*3 = 242.
10 - 2 (ostatnia cyfra) = 8.
8 = 8 (cyfra kontrola.
Zatem powyższy pesel jest prawidłowy.

Spróbujmy napisać funkcję, która będzie robiła to samo co wyżej ale w JavaScripcie. Może ona wyglądać mniej więcej tak:
function isValidPesel(pesel) {
    let weight = [1, 3, 7, 9, 1, 3, 7, 9, 1, 3];
    let sum = 0;
    let controlNumber = parseInt(pesel.substring(10, 11));

    for (let i = 0; i < weight.length; i++) {
        sum += (parseInt(pesel.substring(i, i + 1)) * weight[i]);
    }
    sum = sum % 10;
    return (10 - sum) % 10 === controlNumber;
}
Na początek deklarujemy tablice z wagami, następnie do zmiennej sum przypisujemy 0, zmienna ta będzie odpowiedzialna za sumowanie cyfry * waga. W kolejnej linii do zmiennej controlNumber za pomocą metody substring przypisujemy ostatnią cyfrę z parametru pesel. W pętli mnożymy kolejno każdą cyfrę z odpowiadającą jej wagą, na koniec od 10 odejmujemy resztę z dzielenia przez 10 i jeśli to wyrażenie jest równe naszej zmiennej controlNumber, czyli cyfrze kontrolnej wtedy funkcja zwraca true, czyli pesel prawidłowy, a w przeciwnym przypadku zwraca false. Na koniec przetestujmy naszą funkcję na kilku przykładach:
console.log('Prawidłowy pesel', isValidPesel('64042999928')); //Prawidłowy pesel true
console.log('Prawidłowy pesel', isValidPesel('52022114478')); //Prawidłowy pesel true
console.log('Prawidłowy pesel', isValidPesel('72021706812')); //Prawidłowy pesel true
console.log('Prawidłowy pesel', isValidPesel('80042448774')); //Prawidłowy pesel true
console.log('Prawidłowy pesel', isValidPesel('97031003029')); //Prawidłowy pesel true
console.log('Nieprawidłowy pesel', isValidPesel('97031003021')); //Nieprawidłowy pesel false
console.log('Nieprawidłowy pesel', isValidPesel('97031003023')); //Nieprawidłowy pesel false
console.log('Nieprawidłowy pesel', isValidPesel('')); //Nieprawidłowy pesel false
console.log('Nieprawidłowy pesel', isValidPesel(1)); //Error: pesel.substring is not a function
console.log('Nieprawidłowy pesel', isValidPesel(true)); //Error: pesel.substring is not a function
console.log('Nieprawidłowy pesel', isValidPesel(null)); //Error: pesel is null
Jak widzisz funkcja działa prawidłowo, ale pojawiło się kilka błędów przy niektórych wywołaniach naszej funkcji. Aby temu zapobiec musi dodać sprawdzanie wartości parametru. I ostatecznie nasze metoda powinna wyglądać w ten sposób:
function isValidPesel(pesel) {
    if(typeof pesel !== 'string')
        return false;

    let weight = [1, 3, 7, 9, 1, 3, 7, 9, 1, 3];
    let sum = 0;
    let controlNumber = parseInt(pesel.substring(10, 11));

    for (let i = 0; i < weight.length; i++) {
        sum += (parseInt(pesel.substring(i, i + 1)) * weight[i]);
    }
    sum = sum % 10;
    return (10 - sum) % 10 === controlNumber;
}

console.log('Prawidłowy pesel', isValidPesel('64042999928')); //Prawidłowy pesel true
console.log('Prawidłowy pesel', isValidPesel('52022114478')); //Prawidłowy pesel true
console.log('Prawidłowy pesel', isValidPesel('72021706812')); //Prawidłowy pesel true
console.log('Prawidłowy pesel', isValidPesel('80042448774')); //Prawidłowy pesel true
console.log('Prawidłowy pesel', isValidPesel('97031003029')); //Prawidłowy pesel true
console.log('Nieprawidłowy pesel', isValidPesel('97031003021')); //Nieprawidłowy pesel false
console.log('Nieprawidłowy pesel', isValidPesel('97031003023')); //Nieprawidłowy pesel false
console.log('Nieprawidłowy pesel', isValidPesel('')); //Nieprawidłowy pesel false
console.log('Nieprawidłowy pesel', isValidPesel(1)); //Nieprawidłowy pesel false
console.log('Nieprawidłowy pesel', isValidPesel(true)); //Nieprawidłowy pesel false
console.log('Nieprawidłowy pesel', isValidPesel(null)); //Nieprawidłowy pesel false
Jak widzisz tym razem nie mamy żadnych błędów. Wszystkie wyniki są prawidłowe.

To wszystko co chciałem Ci przekazać w tym artykule. Zapraszam Cię do kolejnych artykułów z serii podstaw programowania w języku JavaScript.

Poprzedni artykuł - Okna dialogowe w JavaScript.
Następny artykuł - Walidacja nip w JavaScript.
Autor artykułu:
Kazimierz Szpin
Kazimierz Szpin
Programista C#/.NET. Głównie pisze aplikacje w ASP.NET MVC, WPF oraz Windows Forms. Specjalizuje się w testach jednostkowych.
Autor bloga ModestProgrammer.pl
Komentarze (8)
Marcin
MARCIN, 12 marca 2019 12:24
Nie uwzględniasz przypadku gdy sum%10 = 0. Wtedy 10-0 = 10. A 10 =/=0
Grzegorz
GRZEGORZ, 19 czerwca 2019 12:40
Walidacja jest tylko na sumę kontrolną. To trochę mało, bo przechodzą PESELe typu: 44444444444 suma się zgadza, ale reszta już nie bardzo. Człowiek urodzony w 44 dniu miesiąca. Przydałoby się doszczelnić, aby: - liczba zbudowana z trzeciej i czwartej cyfry (miesiąc) nie była większa od 32 (dla osób urodzonych do 2100 roku - liczba zbudowana z piątej i szóstej cyfry (dzień) nie była większa od 31
Dawid
DAWID, 23 marca 2020 09:11
Nadal nie ma poprawki dla sytuacji, w której ostatnią cyfrą peselu jest 0
tata
TATA, 11 maja 2020 21:56
W przykładzie jest niby-PESEL 6404299928. Jest on błędny (10 cyfr, powinno być 11). W obliczeniach widać, że zgubiono jedną '9' i PESEL powinien być: 64042999928. Trzeba by nieszczęsną '9' dodać do trzech pozostałych.
Kazimierz Szpin
KAZIMIERZ SZPIN, 7 czerwca 2020 07:30
@MARCIN, @DAWID, dzięki za Wasze uwagi. Dodałem zaproponowaną przez Was zmianę :)
Kazimierz Szpin
KAZIMIERZ SZPIN, 7 czerwca 2020 07:43
@TATA, dzięki faktycznie brakowało 9-tki :)
TATA POWTÓRNIE
TATA POWTÓRNIE, 10 czerwca 2020 18:13
Zajrzałem tu w maju (co widać w komentarzach), skopiowałem funkcję do siebie i teraz (na szczęście w czasie testów) ZONK - nie przechodzą poprawne PESEL-e. Błędy: 1) controlNumber może być jak najbardziej 0, więc należy usunąć wyrażenie: if (controlNumber === 0) return false; 2) sum % 10 też może być 0, i wtedy byłoby 10 - sum = 10 - 0 = 10 (a więc 2 cyfry), dlatego powinno być na końcu: return (10 - sum) % 10 === controlNumber;
Kazimierz Szpin
KAZIMIERZ SZPIN, 10 czerwca 2020 18:23
@TATA POWTÓRNIE, masz racje, wprowadziłem Twoje uwagi :)
Dodaj komentarz
© Copyright 2020 modestprogrammer.pl. Wszelkie prawa zastrzeżone. Polityka prywatności. Design by Kazimierz Szpin