Entering a credit card number is prone to random errors and typos. As a matter of fact, it’s easy to make a mistake in a long chain of digits. Fortunately, we can apply the widely used Luhn algorithm to prevent data corruption.
Implement the Luhn formula in Java
First, I’ll briefly explain the algorithm steps and write some unit tests to verify its implementation. Then, I’ll demonstrate the actual code and describe it thoroughly. If you’re here just for the solution, you can find the code in the Validate credit card numbers with the Luhn algorithm in Java gist.
Understand the algorithm steps
The algorithm description is straightforward:
- Starting at the end of the sequence, add up all the digits, remembering that every odd digit must be multiplied by 2, and if the multiplication result is greater than 9, subtract 9.
- If the remainder of dividing the sum by 10 is 0, the card number is valid.
Validate an example number
|original digits||1||2||8||6||4 [check digit]|
|odd digits multiplied by 2||4||12|
|digits to sum||1||4||8||3 [*]||4|
6 is the first digit multiplied by 2 because it’s located immediately left of the check digit (we are iterating through the digits in the reverse order). Calculating the sum from the third row gives 20. The example “12864” number is valid because 20 mod 10 = 0
[*] Remember that we had to subtract 9
Prepare a test suit
I wrote 6 test cases – three for numbers with a valid check digit and three for erroneous numbers:
Implementing the Luhn algorithm
For your convenience, the plain code is available in the aforementioned gist. Below we’re going to analyze the solution from top to bottom.
As you can deduct from the tests, we need to create the
LuhnFormula class with the
validate() method that accepts the input as a String:
First, we convert the input to the array containing only numeric
characters. If you have to deal with credit card numbers containing “-” or whitespaces the following code will ensure that the algorithm won’t take them into account:
Then, we calculate the sum of elements according to the algorithm rules and verify whether the remainder of dividing the sum by 10 equals 0 or not.
Calculate the sum
Consequently, we can dive into the details of the
As we can see, we instantiate the variable for the sum and iterate through all characters. The code inside the loop solves the following points:
- Get the correct element.
- Convert it to a number.
- Calculate the right value that should be added to the sum.
- Increment the sum.
It’s important to notice that all of those issues are solved in a single loop which helps us keep the computational complexity on a sane level.
Get elements in the right order
getInReverseOrder() method is responsible for providing the right element. In order to calculate the element position we substract 1 from the total amount of characters to avoid
IndexOutOfBoundsException. Furthermore, we subtract the current loop index to receive elements in the reverse order (e.g. when
i=0 we receive the last element, when
i=1 we receive the one before the last):
In the line 6 we convert the received character into an int with the getNumericValue() method. We don’t have to worry about unexpected results because all characters except digits were removed from the input earlier.
Get correct values
We know that we can’t just simply add all elements – we need to calculate a new value for every odd one. Therefore, we check whether the loop index is odd or even. If it’s odd, we double the value and subtract 9 if needed.
In other words, for
i=0, we add the unchanged check digit, for
i=1 we add changed value of the last but one element and so on.
In the final analysis the implementation adheres to the following requirements:
- The algorithm is implemented correctly.
- The matter of optimization is taken into account as we iterate through digits only once.
- Numbers containing separators like “-” or whitespaces are handled accurately. Although support for this edge case is only useful when you can’t be sure that the input contains solely numbers.
Addendum – how to generate random credit card numbers that pass the Luhn algorithm
If you need card numbers that comply with the Luhn formula, you can use Dummy4j – a random data generator that I’ve been contributing to. You can receive 100 credit card numbers that pass this validation with only the following code:
What’s more, you can receive a number for a chosen provider – all it take is to pass a supported provider as an argument:
You can find more in the 12 reasons for using random data generator – introducing Dummy4j post.