LUHN algorithm

From EggeWiki

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>