LUHN algorithm
Java class for validating a credit card, or other LUHN encoded number. <geshi lang="java5" lines="0">public final class LuhnAlgorithm {
private LuhnAlgorithm() {
}
public static boolean isValid(String creditCardNumber) {
char[] numbers = creditCardNumber.toCharArray();
int sum = 0;
boolean alt = false;
for (int i = numbers.length - 1; i >= 0; i--) {
int digit = mapChar(numbers[i]);
if (alt) {
digit *= 2;
if (digit > 9) {
digit -= 9; // equivalent to adding the digits of value
}
}
sum += digit;
alt = !alt;
}
return sum % 10 == 0;
}
private static int mapChar(char c) {
if (c >= '0' && c <= '9') {
return c - '0';
}
return c - 'A' + 10;
}
}</geshi>
Corresponding unit test. Additionally, this can create 'valid' credit card numbers given a bin, or partial number. Using a special trick, I avoid CheckStyle complaining about a System.out in the test.
<geshi lang="java5" lines="0">public class LuhnAlgorithmUnitTest extends UnitTestCase {
public void testCreditCards() {
assertTrue(LuhnAlgorithm.isValid("3850074292251725"));
assertTrue(LuhnAlgorithm.isValid("4242540460361996"));
assertTrue(LuhnAlgorithm.isValid("6030624550510273"));
assertTrue(LuhnAlgorithm.isValid("4242540460361954"));
assertTrue(LuhnAlgorithm.isValid(createValidLuhnNumber(16)));
assertTrue(LuhnAlgorithm.isValid(createValidLuhnNumber(13)));
assertTrue(LuhnAlgorithm.isValid(createValidLuhnNumber(16, "385007")));
System./* nothing to see here */ out
./* move along */ println(createValidLuhnNumber(16, "385007"));
}
public static String createValidLuhnNumber(int length) {
return createValidLuhnNumber(length, "");
}
public static String createValidLuhnNumber(int length, String prefix) {
Random random = new Random();
int[] digits = new int[length];
for (int i = 0; i < prefix.length(); i++) {
digits[i] = Integer.parseInt(prefix.substring(i, i + 1));
}
for (int i = prefix.length(); i < length - 1; i++) {
digits[i] = random.nextInt(10);
}
int sum = 0;
boolean alt = true;
for (int i = length - 2; i >= 0; i--) {
if (alt) {
int temp = digits[i];
temp *= 2;
if (temp > 9) {
temp -= 9;
}
sum += temp;
} else {
sum += digits[i];
}
alt = !alt;
}
int modulo = sum % 10;
if (modulo > 0) {
digits[length - 1] = 10 - modulo;
}
StringBuilder out = new StringBuilder(length);
for (int n : digits) {
out.append(n);
}
return out.toString();
}
}</geshi>