LUHN algorithm

From EggeWiki
Jump to: navigation, search

Java class for validating a credit card, or other LUHN encoded number.

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;
    }
}

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.

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();
    }
}
Personal tools