[oak perl] Re: Customizing a Barcode Checkdigit Subroutine

David B. Peterson dave at toppledwagon.com
Sat Dec 21 15:52:34 CST 2002


There is an interesting property of numbers that you can use for this 
calculation.

If you add the individual digits of a number and subtract 9 from it 
as many times as necessary, you will eventually get the sum of the 
two numbers.

So, if you have a number such as 17  1+7 = 8, 17-9 = 8 too.  Since 
you are only dealing with single digits multiplied by 2, the highest 
number you will use is 18.  So you will only need to ever subtract 9 
once.

I believe your library card system uses what we call a LUHN-10 check. 
This is the same check used to determine a 'valid' credit card number 
(for some definition of valid. :)  This works for visa, mastercard, 
american express, discover, and many others.

Here is a little routine I wrote a hell of a long time ago for this purpose.

sub LUHN10 {
   my ($a, @cc, $sum);
   my ($cc = @_[0]);
   $cc =~ tr/0-9//cd;
   @cc = split('', $cc);
   while (@cc) {
     $sum += pop(@cc);
     $a = pop(@cc) * 2;
     $a -= 9 if $a > 9;
     $sum += $a;
   }
   return (!($sum % 10));
}

used as such:

LUHN10('visa: 4444444444445555');
LUHN10('4444 4444 4444 5555');

It doesn't care about any non digit chars.

<rant>
And as such, I'm always disgusted by commerce sites that require me 
to leave the spaces out of my credit card number.  It shouldn't 
matter one iota to the computer, but it sure makes it easier for me 
to see if I've made a typo when I can put spaces in there.
</rant>

Have fun.

-Dave



More information about the Oakland mailing list