in reply to Summing the odd/even digits of a larger number (for upc check digits)...a better way?
perl -le'$m=1;$s+=$_*($m^=2)for(split(//,$ARGV[0])); print(($s%10)?"BAD":"OK");'
OK, that's probably not very helpful, but contains a few useful things for a real implementation. First, you can sum the digits as you go along; you don't have to add first, then multiply. Second, odd digits get multiplied by 3 and even by 1; you can toggle between 3 and 1 by twiddling the 2 bit (since 3 ^ 2 == 1 and 1 ^ 2 == 3). Third, taking the sum, subtracting from the next highest multiple of 10, then comparing it to the check digit is the same as adding the check digit, taking the result modulo 10, and comparing to 0. Fourth, I've only been thinking about this problem for about 10 minutes, so please correct me if I'm wrong, but it does work with the test UPC. :-)
That leads to the more reasonable code:
sub check_upc { my($upc)=@_; my $m = 1; for(split(//,$upc)) { $s += $_ * ($m^=2); } return (($s%10)?"Invalid checkdigit; should be @{[10-($s-chop($upc)) +%10]}" :undef); }
|
|---|