Strona główna » Algorytmy » Artykuły » PESEL
 

PESEL

PESEL

Numer PESEL składa się z 11 cyfr. W jego skład wchodzi data urodzenia, liczbą porządkowa, kod płci oraz cyfr kontrolna. Każdej osobie fizycznym jest przypisany dokładnie jeden numer PESEL. Ze względu na informacje w nim zawarte, jest on traktowany jako część danych osobowych. Oto jak tworzy się numer PESEL:

Data urodzenia

RRMMDD-----

Data urodzenia jest zapisana na pierwszych 6 cyfrach numeru PESEL. Pierwsze dwie cyfry to dwie ostatnie cyfry roku. Dwie kolejne to miesiąc, a dwie kolejne to dzień. We wszystkich przypadkach jeśli istnieje potrzeba to dopisujemy zero, aby długość danego fragmentu zawsze wynosiła dwa.

Jednak takie rozwiązanie powodowało problem: obcięcie dwóch pierwszych cyfr roku nie pozwalało na rozróżnienie osób urodzonych w różnych stuleciach tego samego dnia i miesiąca. Przyjętym rozwiązaniem została modyfikacja numeru miesiąca. W zależności od stulecia do numeru miesiąca jest dodawana odpowiednia wartość zgodnie z poniższą tabelką:

LataDodawana wartość
1800 - 189980
1900 - 19990
2000 - 209920
2100 - 219940
2200 - 229960

Dzięki takiemu zabiegowi jesteśmy w stanie rozpoznać czy dana osoba została urodzona 1 stycznia 1900 r. czy 1 stycznia 2000 r. W pierwszym przypadku kod miesiąca to będzie 01, a w drugim 21.

Implementacja

Zakładamy, że numer PESEL wczytamy od użytkownika jako tablice znaków. Wtedy odczytywanie danych będzie wygodniejsze niż w przypadku wczytania PESELU jako liczby. W celu wygodnego zamiany znaku cyfry na liczbę napiszemy funkcję digitChar():

  1. int digitChar(const char c){
  2.   return c - '0';
  3. }

Funkcja birthDay() pozwala na wyłuskanie z numeru PESEL daty urodzenia. Dane sformatujemy w taki sposób, aby były czytelniejsze dla przeciętnej osoby.

  1. void birthDay(const char* pesel){
  2.   int year = digitChar(pesel[0]) * 10 + digitChar(pesel[1]) + ((digitChar(pesel[2]) / 2 + 1) % 5) * 100 + 1800;
  3.   int month = (digitChar(pesel[2]) % 2) * 10 + digitChar(pesel[3]);
  4.   int day = digitChar(pesel[4]) * 10 + digitChar(pesel[5]);
  5.   cout << day << "." << month << "." << year << endl;
  6. }

(1.) Wynik wypiszemy na konsolę - nie będziemy go zwracać. Jako argument funkcja przyjmuje pesel - pesel przekazany jako słowo. (2.) Obliczamy rok urodzenia. Ostatnie dwie cyfry są proste do obliczenia. Problemem może być tu wyliczenie stulecia. Istnieje możliwość wyliczenia go na podstawie pierwszej cyfry miesiąca. W tym celu cyfrę dzielimy na dwa i obcinamy część ułamkową. Wtedy dla 18** uzyskamy 5, a dla 19** 0. Dodając następnie 1 i wyciągajac modulo 5 uzyskamy dla 18** 0, a dla 19** 1. Taką liczbę już możemy pomnożyć razy 100. Do całości dodajemy 1800. (3.) Wyliczamy numer miesiąca. Należy tu pamiętać, że pierwszy cyfra jest zmodyfikowana przez określenie stulecia. (4.) Wyliczenie dnia nie powinno stanowić problemu. (5.) Wypisujemy wynik w postaci DD.MM.RRRR.

Numeri serii i płeć

------SSSP-

Kolejne cztery cyfry (od 7 do 10) oznaczają numer serii PESELU. Znacząca jest tu cyfra 10. Oznacza ona płeć. Dla kobiet zarezerwowane są liczby parzyste (0, 2, 4, 6, 8), a dla mężczyzn nieparzyste (1, 3, 5, 7, 9).

Implementacja

Sprawdzenie płci nie powinno stanowić problemu:

  1. void gender(const char* pesel){
  2.   cout << ((digitChar(pesel[9]) % 2 == 0) ? "kobieta" : "mezczyzna") << endl;
  3. }

Cyfra kontrolna

----------K

Jedenasta cyfra pozwala na wykrycie błędów w numerze PESEL. Cyfrę kontrolną oblicza się sumując wszystkie cyfry (prócz ostatniej), gdzie każda cyfra jest mnożona przez odpowiedni mnożnik. Następnie pobieramy resztę z dzielenia obliczonej sumy przez 10. Potem odejmuje od dziesięciu resztę. Jeśli wyliczona cyfra kontrolna nie zgadza się z 11 cyfrą to w PESELU jest błąd. W tabeli przedstawione są mnożniki dla każdej cyfry:

Nr. Cyfry12345678910
Mnożnik1379137913

Implementacja

Wszystkie mnożniki liczby można przechowywać w oddzielnej tablicy. Niemniej lepszym wyjściem będzie wyliczenie mnożnika na podstawie podanej pozycji:

  1. bool isValid(const char* pesel) {
  2.   int suma = 0;
  3.   for(int i = 0; i < 10; i++){
  4.     suma += digitChar(pesel[i]) * (1 + (i % 2) * 2 + ((i / 2) % 2) * 6);
  5.   }
  6.   return digitChar(pesel[10]) == (10 - (suma % 10)) % 10;
  7. }

(2.) Zerujemy sumę cyfr. (3.) Dla każdej cyfry od pierwszej do 10: (4.) pobieramy i-tą cyfrę i mnożymy przez odpowiedni mnożnik. (5.) Na koniec zwracamy porównanie ostatniej cyfry podanego numeru pesel z wyliczoną cyfrą kontrolną. Wynik 10 - reszta dzielimy znów przez 10 i wyciągamy resztę, ponieważ jeśli reszta sumy wyniosła 0 to 10 - 0 = 10. To mogłoby spowodować błędne rozpoznawanie numeru pesel.

Testowanie funkcji

Przykładowy program, który sprawdzić poprawność PESELu i wypisze dane w nim zawarte w przypadku poprawności danych:

  1. int main () {
  2.   char* pesel = new char[12];
  3.   cin >> pesel;
  4.   if(isValid(pesel)){
  5.     cout << "PESEL prawidlowy\n";
  6.     birthDay(pesel);
  7.     gender(pesel);
  8.   } else {
  9.     cout << "PESEL nieprawidlowy\n";
  10.   }
  11.   system("pause");
  12.   return 0;
  13. }

Zadania

Zadanie 1

Napisz program, który dla podanej daty w formacie DD.MM.RRRR oraz płci podanej jako pojedynczy znak K (kobieta) lub M (mężczyzna) poda przykładowy numer PESEL. Zakładamy, że numer serii losujemy.

Przykładowo dla podania wartości daty 01.01.2016 i znaku M zostanie przykładowo wypisane na ekran:

  1. 16210101235