Sunday, July 18, 2010

LUHN Algorithm in C# and LINQ

(Copyright from: Just Agile.com)
The LUHN algorithm is commonly used in credit card verification schemes on e-commerce websites. It provides a simple means of verifying that a user has entered their credit card number correctly.
The LUHN algorithm works by taking a series of digits and applying a checksum. The digits are valid if the checksum modulo 10 is equal to 0.
The checksum is calculated as follows: assuming each digit is indexed from right to left: D(N)D(N - 1)...D(4)D(3)D(2)D(1), then compute the sum D(1) + 2 x D(2) + D(3) + 2 x D(4) + D(5) + 2 x D(6) + etc. Basically, every even digit in the sum is doubled. The remainder of the sum after dividing by 10 gives the final value of the checksum.

LUHN Checksum

It's a great example of LINQ and I don't think you'll find a more concise implementation anywhere else (one line if you remove the formatting, and it handles removing white space)!
public static int ComputeChecksum(string value)
{
    return value
        .Where(c => Char.IsDigit(c))
        .Reverse()
        .SelectMany((c, i) => ((c - '0') << (i & 1)).ToString())
        .Sum(c => c - '0') % 10;
}
To validate based on the checksum:
public static bool IsValid(string value)
{
   return ComputeChecksum(value) == 0;
}
This example uses the following namespaces:
using System;
using System.Collections.Generic;
using System.Linq;

Notes

Wikipedia states that some credit card companies allow 5 as well as 0 to be valid values for the checksum, however, I've never come accross this scenario in the UK, so let me know if you have!

2 comments:

MrAntix said...

thanks Peter - saved me a think :)

Unknown said...

I think you may be missing a part of the algorithm. Once you double the number (or not), you need to subtract 9 from all numbers>9.

ie

CreditCard.Where(Char.IsDigit).Reverse().Select((c, p) => c-'0' << (p & 1)).Select(n => n > 9 ? n - 9 : n).Sum() % 10 != 0