Luhn algorithm
View on WikipediaThe Luhn algorithm or Luhn formula (creator: IBM scientist Hans Peter Luhn), also known as the "modulus 10" or "mod 10" algorithm, is a simple check digit formula used to validate a variety of identification numbers. [a] The purpose is to design a numbering scheme in such a way that when a human is entering a number, a computer can quickly check it for errors.
The algorithm is in the public domain and is in wide use today. It is specified in ISO/IEC 7812-1.[2] It is not intended to be a cryptographically secure hash function; it was designed to protect against accidental errors, not malicious attacks. Most credit card numbers and many government identification numbers use the algorithm as a simple method of distinguishing valid numbers from mistyped or otherwise incorrect numbers.
Description
[edit]The check digit is computed as follows:
- Drop the check digit from the number (if it's already present). This leaves the payload.
- Start with the payload digits. Moving from right to left, double every second digit, starting from the last digit. If doubling a digit results in a value > 9, subtract 9 from it (or sum its digits).
- Sum all the resulting digits (including the ones that were not doubled).
- The check digit is calculated by , where s is the sum from step 3. This is the smallest number (possibly zero) that must be added to to make a multiple of 10. Other valid formulas giving the same value are , , and . Note that the formula will not work in all environments due to differences in how negative numbers are handled by the modulo operation.
Example for computing check digit
[edit]Assume an example of an account number 1789372997 (just the "payload", check digit not yet included):
| Digits reversed | 7 | 9 | 9 | 2 | 7 | 3 | 9 | 8 | 7 | 1 |
|---|---|---|---|---|---|---|---|---|---|---|
| Multipliers | 2 | 1 | 2 | 1 | 2 | 1 | 2 | 1 | 2 | 1 |
| = | = | = | = | = | = | = | = | = | = | |
| 14 | 9 | 18 | 2 | 14 | 3 | 18 | 8 | 14 | 1 | |
| Sum digits | 5 (1+4) |
9 |
9 (1+8) |
2 |
5 (1+4) |
3 |
9 (1+8) |
8 |
5 (1+4) |
1 |
The sum of the resulting digits is 56.
The check digit is equal to .
This makes the full account number read 17893729974.
Example for validating check digit
[edit]- Drop the check digit (last digit) of the number to validate. (e.g. 17893729974 → 1789372997)
- Calculate the check digit (see above)
- Compare your result with the original check digit. If both numbers match, the result is valid. (e.g. (givenCheckDigit = calculatedCheckDigit) ⇔ (isValidCheckDigit)).
Strengths and weaknesses
[edit]The Luhn algorithm will detect all single-digit errors, as well as almost all transpositions of adjacent digits. It will not, however, detect transposition of the two-digit sequence 09 to 90 (or vice versa). It will detect most of the possible twin errors (it will not detect 22 ↔ 55, 33 ↔ 66 or 44 ↔ 77).
Other, more complex check-digit algorithms (such as the Verhoeff algorithm and the Damm algorithm) can detect more transcription errors. The Luhn mod N algorithm is an extension that supports non-numerical strings.
Because the algorithm operates on the digits in a right-to-left manner and zero digits affect the result only if they cause shift in position, zero-padding the beginning of a string of numbers does not affect the calculation. Therefore, systems that pad to a specific number of digits (by converting 1234 to 0001234 for instance) can perform Luhn validation before or after the padding and achieve the same result.
The algorithm appeared in a United States Patent[1] for a simple, hand-held, mechanical device for computing the checksum. The device took the mod 10 sum by mechanical means. The substitution digits, that is, the results of the double and reduce procedure, were not produced mechanically. Rather, the digits were marked in their permuted order on the body of the machine.
Pseudocode implementation
[edit]The following function takes a card number, including the check digit, as an array of integers and outputs true if the check digit is correct, false otherwise.
function isValid(cardNumber[1..length])
sum := 0
parity := length mod 2
for i from 1 to (length - 1) do
if i mod 2 == parity then
sum := sum + cardNumber[i]
elseif cardNumber[i] > 4 then
sum := sum + 2 * cardNumber[i] - 9
else
sum := sum + 2 * cardNumber[i]
end if
end for
return cardNumber[length] == ((10 - (sum mod 10)) mod 10)
end function
Uses
[edit]The Luhn algorithm is used in a variety of systems, including:
- Credit card numbers
- IMEI numbers
- CUSIP numbers for North American financial instruments
- National Provider Identifier numbers in the United States
- Canadian social insurance numbers
- Israeli ID numbers
- South African ID numbers
- South African Tax reference numbers
- Swedish Personal identity numbers
- Swedish Corporate Identity Numbers (OrgNr)
- Greek Social Security Numbers (ΑΜΚΑ)
- ICCID of SIM cards
- European patent application numbers
- Survey codes appearing on McDonald's, Taco Bell, and Tractor Supply Co. receipts
- United States Postal Service package tracking numbers use a modified Luhn algorithm[3]
- Italian VAT numbers (Partita Iva)[4]
References
[edit]- ^ a b US patent 2950048A, Luhn, Hans Peter, "Computer for Verifying Numbers", published 23 August 1960, issued 23 August 1960
- ^ "Annex B: Luhn formula for computing modulus-10 "double-add-double" check digits". Identification cards — Identification of issuers — Part 1: Numbering system (standard). International Organization for Standardization & International Electrotechnical Commission. January 2017. ISO/IEC 7812-1:2017.
- ^ Publication 199: Intelligent Mail Package Barcode (IMpb) Implementation Guide for Confirmation Services and Electronic Payment Systems (PDF) (28th ed.). United States: United States Postal Service. 10 October 2023. Archived (PDF) from the original on 17 November 2023. Retrieved 29 November 2023.
- ^ Albanese, Ilenia (10 August 2022). "A cosa serve la Partita Iva? Ecco cosa sapere" [What is a VAT number for? Here's what to know]. Partitaiva.it (in Italian). Archived from the original on 29 June 2024. Retrieved 29 June 2024.
Notes
[edit]External links
[edit]- Luhn test of credit card numbers on Rosetta Code: Luhn algorithm/formula implementation in 160 programming languages as of 22 July 2024[ref]
Luhn algorithm
View on GrokipediaOverview
Definition and Purpose
The Luhn algorithm is a simple checksum formula used to validate identification numbers by generating or verifying a check digit appended to the sequence.[5][3] It was developed by Hans Peter Luhn, an IBM researcher, and patented in 1960.[6][3] The primary purpose of the algorithm is to detect accidental errors during data entry or transmission, such as single-digit substitutions or transpositions of adjacent digits, while offering no protection against deliberate tampering.[5][2] It processes decimal digits from right to left, with the check digit serving as the rightmost element to ensure the overall sum meets a validation criterion.[3]Historical Context
The Luhn algorithm was invented by Hans Peter Luhn, a researcher and engineer at IBM, who filed a U.S. patent application for a mechanical device to compute and verify check digits on January 6, 1954.[3] The patent, titled "Computer for Verifying Numbers," was granted on August 23, 1960, as U.S. Patent No. 2,950,048.[3] Luhn's work addressed the growing need for reliable error detection in early data processing environments, where manual entry and mechanical handling of numerical data were prone to mistakes such as digit transpositions or omissions.[7] This development occurred amid IBM's dominance in punched-card systems for accounting and information management during the 1950s, when such technologies were essential for business operations like inventory tracking, billing, and order fulfillment.[8] Luhn's algorithm provided a simple, non-cryptographic method to append a check digit to multi-digit numbers, enabling quick validation without complex computations, which was particularly valuable for the era's electromechanical accounting machines.[9] As credit card systems emerged in the late 1950s and expanded through the 1960s, the Luhn algorithm was integrated into early numbering schemes to ensure data integrity during manual and machine-based transactions. Its public domain status facilitated broad, royalty-free use across industries. Later, it was formalized in international standards, notably incorporated into ISO/IEC 7812-1:2017 as the prescribed method for computing check digits on identification cards, including those for financial applications.[10]Algorithm Description
Step-by-Step Process
The Luhn algorithm operates on a sequence of decimal digits, where the rightmost digit serves as the check digit, and the doubling process begins on the second position from the right, ensuring consistent application regardless of the number's length. This positioning rule allows the algorithm to function uniformly for identification numbers of varying lengths, from short codes to longer account numbers, by always anchoring the check digit at the end.[2] To validate a complete number using the Luhn algorithm, the process begins by identifying the check digit as the rightmost position and excluding it from initial processing. Starting from the right and moving leftward, every second digit (positions 2, 4, 6, etc., counting from the right) is doubled. For each doubled value, if the result exceeds 9, it is adjusted by subtracting 9 (equivalently, summing its individual digits to handle the carry). The unmodified digits in the odd positions (1, 3, 5, etc., from the right, excluding the check digit) remain as is. All processed doubled values and unmodified digits are then summed, and the check digit is added to this total. If the final sum is divisible by 10 (i.e., sum modulo 10 equals 0), the number is valid.[11] For computing the check digit to append to a base number, the same preparatory steps are followed: exclude any existing check position, double every second digit from the right (starting at position 2), adjust doubled values greater than 9 by subtracting 9, and sum all processed and unmodified digits. The check digit is then calculated as (10 minus the sum modulo 10), taken modulo 10 to ensure it is a single digit from 0 to 9. This appends a value that makes the complete number's sum divisible by 10 when validated.[2]Mathematical Formulation
The Luhn algorithm is defined for a sequence of digits , where is the check digit and the indices correspond to positions from left to right, with position numbering starting from the rightmost digit as position 1 (). Positions are counted from the right, with odd-numbered positions (1, 3, 5, ...) using the digit as is and even-numbered positions (2, 4, 6, ...) applying a doubling transformation.[11] The doubling function is formally if , and if (since for digit ). The validation sum is thenExamples
Computing the Check Digit
To compute the check digit, process the base number from right to left, doubling every second digit starting with the rightmost digit of the base (which will become the second position from the right in the full number), and apply the digit sum rule (sum digits or subtract 9) to any doubled value of 10 or greater. Calculate the sum of all processed digits; the check digit is the smallest non-negative integer (0-9) that makes the total sum divisible by 10.[3] Consider the base number 7992739871 as an example. The positions to double are the 1st, 3rd, 5th, 7th, and 9th from the right: digits 1, 8, 3, 2, 9. The doubled values are: 1×2=2, 8×2=16 (1+6=7), 3×2=6, 2×2=4, 9×2=18 (1+8=9). The non-doubled digits sum to 7+7+9+7+9=39? Wait, digits: from left 7,9,9,2,7,3,9,8,7,1; non-doubled pos2=7, pos4=9, pos6=7, pos8=9, pos10=7 sum 7+9+7+9+7=39. Processed doubled: 2+7+6+4+9=28. Total sum=39+28=67. The check digit is 10 − (67 mod 10) = 10 − 7 = 3, resulting in the full number 79927398713. The following table illustrates the process for the base number, with positions numbered from the right (pos1 rightmost, doubled), running sum accumulated from right to left:| Position from right | Digit | Doubled? | Processed Value | Running Sum |
|---|---|---|---|---|
| 1 | 1 | Yes | 2 | 2 |
| 2 | 7 | No | 7 | 9 |
| 3 | 8 | Yes | 7 | 16 |
| 4 | 9 | No | 9 | 25 |
| 5 | 3 | Yes | 6 | 31 |
| 6 | 7 | No | 7 | 38 |
| 7 | 2 | Yes | 4 | 42 |
| 8 | 9 | No | 9 | 51 |
| 9 | 9 | Yes | 9 | 60 |
| 10 | 7 | No | 7 | 67 |
Validating an Identification Number
To validate an identification number using the Luhn algorithm, process the entire number from right to left, doubling every second digit starting from the second position from the right (results over 9 reduced by summing digits or subtracting 9), sum all processed values; the number is valid if the total modulo 10 equals 0.[3] This confirms the check digit balances the preceding digits. Consider the complete number 79927398713. The processed values sum to 70, and 70 mod 10 = 0, so valid.[12] The following table illustrates the step-by-step processing for 79927398713, positions from the right (position 1 rightmost, not doubled):| Position (from right) | Digit | Double? | Processed Value |
|---|---|---|---|
| 1 | 3 | No | 3 |
| 2 | 1 | Yes | 2 (1×2) |
| 3 | 7 | No | 7 |
| 4 | 8 | Yes | 7 (8×2=16, 1+6) |
| 5 | 9 | No | 9 |
| 6 | 3 | Yes | 6 (3×2) |
| 7 | 7 | No | 7 |
| 8 | 2 | Yes | 4 (2×2) |
| 9 | 9 | No | 9 |
| 10 | 9 | Yes | 9 (9×2=18, 1+8) |
| 11 | 7 | No | 7 |
Implementation
Pseudocode
The Luhn algorithm can be expressed in pseudocode to illustrate its core logic for both validating a complete number (including its check digit) and computing a check digit for a partial number. These representations assume the input is a string of digits, preserving leading zeros if present, and process the digits from right to left for consistency with common implementations. The validation function computes a weighted sum where every second digit (starting from the rightmost, which is position 1 and remains undoubled) is doubled and adjusted if necessary, then checks if the total sum is divisible by 10.[3] For edge cases, an empty string or single-digit input should return false for validation (as they lack sufficient digits for meaningful checking) or indicate invalid input for check digit computation. The following pseudocode outlines these operations in a language-agnostic manner.Validation Pseudocode
function isValid(number: [string](/page/String)): [boolean](/page/Boolean)
if length(number) < 2 then
return false // Edge case: too few digits
end if
sum = 0
isEvenPosition = false // Starting from right: position 1 (rightmost) is odd, no double
for i = length(number) - 1 downto 0 do // Process from right to left
digit = integer(number[i])
if isEvenPosition then
doubled = 2 * digit
sum += if doubled > 9 then doubled - 9 else doubled
else
sum += digit
end if
isEvenPosition = not isEvenPosition
end for
return sum % 10 == 0
end function
This pseudocode reverses the processing direction implicitly by iterating from the end, ensuring the rightmost digit is not doubled, as described in the original method for error detection.[3]
Check Digit Computation Pseudocode
function computeCheckDigit(number: string): [integer](/page/Integer)
if [length](/page/Length)(number) == 0 then
return -1 // [Edge case](/page/Edge_case): invalid input
end if
sum = 0
isEvenPosition = true // Starting from right of base: rightmost base digit is position 2 in full number (even, double)
for i = [length](/page/Length)(number) - 1 downto 0 do
digit = [integer](/page/Integer)(number[i])
if isEvenPosition then
doubled = 2 * digit
sum += if doubled > 9 then doubled - 9 else doubled
else
sum += digit
end if
isEvenPosition = not isEvenPosition
end for
checkDigit = (10 - (sum % 10)) % 10
return checkDigit
end function
The computation excludes the check digit position, treating the input as the base number, and derives the digit that would make the full sum divisible by 10 when appended. This mirrors the validation logic but solves for the final digit.[3]
Practical Considerations
The Luhn algorithm operates with O(n time complexity, where n represents the number of digits in the input, as it requires a single pass through the sequence to compute the checksum.[12] This efficiency ensures minimal computational overhead, making it ideal for real-time validation in payment processing systems, where it enables instant error detection without significant delays.[5][1] Implementations in various programming languages leverage built-in functions for concise execution. In Python, a typical validation function processes the digits in reverse and applies the doubling rule selectively:def is_luhn_valid(number):
digits = [int(d) for d in str(number)][::-1]
total = 0
for i, d in enumerate(digits):
if i % 2 == 1:
d *= 2
if d > 9:
d -= 9
total += d
return total % 10 == 0
[12]
In JavaScript, the reduce method facilitates a functional approach:
function isLuhnValid(number) {
const digits = number.toString().split('').reverse().map(Number);
const sum = digits.reduce((acc, digit, i) => {
let val = digit;
if (i % 2 === 1) {
val *= 2;
if (val > 9) val -= 9;
}
return acc + val;
}, 0);
return sum % 10 === 0;
}
[12]
Error handling is crucial in practical deployments; functions must reject non-numeric inputs by validating that the provided string consists solely of digits, preventing invalid computations.[5] The algorithm inherently supports variable-length inputs without requiring a fixed modulo beyond base 10, accommodating identifiers from 10 to 19 digits or more.[12]
For enhanced performance in scenarios like user input streams, optimizations avoid full string reversal by iterating from the right and maintaining a running total, allowing incremental processing as digits arrive.[2] This approach aligns with the core pseudocode logic while reducing memory operations for large or dynamic inputs.
Testing implementations should include unit tests for valid numbers, single-digit errors, and adjacent transpositions, as the algorithm detects nearly all such common input mistakes to ensure reliability in production environments.[2]