Skip to content

Algorithms

This page documents the checksum and structural validation algorithms implemented by Numerik. All validation is digit-array arithmetic — no regular expressions are used.

Weights: 1, 3, 7, 9, 1, 3, 7, 9, 1, 3

  1. Strip whitespace. Reject inputs longer than 32 characters. Assert exactly 11 digits; fail with InvalidLength otherwise.
  2. Reject non-digit characters; fail with InvalidCharacters.
  3. Decode the birth date using the century encoding table below. Fail with InvalidMonth if the stored month does not fall in any known range. Fail with InvalidDate if the decoded date is not a real calendar date. In strict mode, fail with FutureDate if the birth date is in the future.
  4. Compute the checksum: multiply each of the first 10 digits by its corresponding weight and sum the results. Take sum mod 10, subtract from 10, take mod 10 again. The result must equal digit 11; fail with InvalidChecksum otherwise.
  5. In strict mode, reject inputs where all 11 digits are identical; fail with AllSameDigit.

The PESEL month digits encode both the birth month and the birth century by adding an offset:

Stored month rangeReal monthBirth century
01 – 1201 – 121900 – 1999
21 – 3201 – 122000 – 2099
41 – 5201 – 122100 – 2199
61 – 7201 – 122200 – 2299
81 – 9201 – 121800 – 1899

Input: 9 2 0 6 0 5 1 2 1 8 6

PositionDigitWeightProduct
1919
2236
3070
46954
5010
65315
7177
82918
9111
108324

Sum = 9 + 6 + 0 + 54 + 0 + 15 + 7 + 18 + 1 + 24 = 134

134 mod 10 = 410 - 4 = 66 mod 10 = 6 — digit 11 is 6


Weights: 6, 5, 7, 2, 3, 4, 5, 6, 7

  1. Strip hyphens and spaces. Reject inputs longer than 32 characters. Assert exactly 10 digits; fail with InvalidLength.
  2. Reject non-digit characters; fail with InvalidCharacters.
  3. Assert the first 3 digits are not 000; fail with InvalidFormat.
  4. Multiply each of the first 9 digits by its weight. Sum the products. Take sum mod 11. The result must equal digit 10; since a single digit can only be 0–9, a modulo result of 10 can never match and always fails with InvalidChecksum.

Input: 5 2 6 0 2 5 0 2 7 4

PositionDigitWeightProduct
15630
22510
36742
4020
5236
65420
7050
82612
97749

Sum = 30 + 10 + 42 + 0 + 6 + 20 + 0 + 12 + 49 = 169

169 mod 11 = 4 — digit 10 is 4


REGON uses a two-stage algorithm. The 14-digit form first validates the base 9 digits before validating the full 14.

Weights: 8, 9, 2, 3, 4, 5, 6, 7

  1. Strip whitespace. Assert exactly 9 digits.
  2. Multiply the first 8 digits by the 9-digit weights. Sum. Take sum mod 11. If the result is 10, the checksum digit must be 0. Otherwise the result must equal digit 9.

Weights: 2, 4, 8, 5, 0, 9, 7, 3, 6, 1, 2, 4, 8

  1. Strip whitespace. Assert exactly 14 digits.
  2. Validate digits 1–9 as a standalone 9-digit REGON (see above).
  3. Multiply the first 13 digits by the 14-digit weights. Sum. Take sum mod 11. If the result is 10, digit 14 must be 0. Otherwise the result must equal digit 14.

KRS has no public checksum algorithm. It is a sequential registry number assigned by the court register. Numerik validates format and range only:

  1. Strip whitespace. Reject inputs longer than 32 characters. Assert ≤ 10 digits.
  2. Reject non-digit characters.
  3. Assert numeric value is greater than 0; fail with AllZeros.
  4. In strict mode, zero-pad to 10 digits and reject inputs where all digits are identical; fail with AllSameDigit.

For authoritative verification that a KRS number is actually assigned, query the official KRS registry API.


NRB uses the standard IBAN MOD-97 algorithm:

  1. Strip spaces and hyphens. Strip the optional PL country prefix. Reject inputs over 40 characters.
  2. Assert exactly 26 digits remain.
  3. Assert all characters are digits.
  4. Rearrange as: digits 3–26 (the BBAN) + 2521 (numeric encoding of PL) + digits 1–2 (check digits).
  5. Compute the resulting number modulo 97. The result must equal 1.

VAT-EU validation is a thin wrapper over NIP:

  1. Strip spaces and hyphens. Reject inputs over 32 characters.
  2. Assert the first two characters are PL (case-insensitive); fail with InvalidFormat.
  3. Strip the prefix. Assert exactly 10 digits remain.
  4. Apply the full NIP algorithm to the extracted digits.

IBAN validation is a thin wrapper over NRB:

  1. Strip spaces and hyphens. Reject inputs over 40 characters.
  2. Assert the first two characters are PL (case-insensitive); fail with InvalidFormat.
  3. Strip the prefix. Assert exactly 26 digits remain.
  4. Apply the full NRB MOD-97 algorithm to the extracted digits.

Used by both ID Card and Passport — the same international standard applied to travel document numbers.

Weights: 7, 3, 1 repeating over positions 1–8 (8 input characters). Position 9 is the check digit.

Character values:

  • Digits 09 → face value (09)
  • Letters AZ1035 (A=10, B=11, … Z=35)
  1. Strip spaces and hyphens. Convert to uppercase. Reject inputs over 32 characters.
  2. Assert exactly 9 characters; fail with InvalidLength.
  3. Validate character types per identifier (see individual pages).
  4. Multiply each of the first 8 characters by its weight and sum the products.
  5. Compute sum mod 10. The result must equal the 9th character; fail with InvalidChecksum.

Number: A B C 1 2 3 4 5 4 (ID card)

PositionCharValueWeightProduct
1A10770
2B11333
3C12112
41177
52236
63313
744728
855315

Sum = 70 + 33 + 12 + 7 + 6 + 3 + 28 + 15 = 174

174 mod 10 = 4 — position 9 is 4

If this saved you time → ☕ Buy me a coffee