I have to calculate a check digit for a 20-digit barcode. I have a spec which includes some pseudo code but it looks nasty. Particularly the part with division & quotient. There's plenty of scope for this to fail with loss of precision or rounding etc. I want to know if this is a recognised checksum so that I can use a tested implementation, ideally in c# or java.
Info and code:
ORIGNO; Type = String. Description: Any length barcode string excluding the check digit in the last position. Example: A 21 character Toll Connect barcode string has the check digit in the last (21st) position. Therefore the ORIGNO would be the first 20 characters of the 21 character Toll Connect barcode string.
PRODUCTNO = 0; type=integer
LENGTHNO = Length (ORIGNO)
MULTIPLIER=3
For LP = LENGTHNO to 1 step -1
CHARTOCHECK=MID (ORIGNO,LP,1)
IF isnumeric (CHARTOCHECK) then
DIGIT = asc (CHARTOCHECK) - asc ('0')
else
DIGIT = rem ((asc (CHARTOCHECK)-asc ('A')) / 10)
endif
PRODUCTNO = PRODUCTNO + DIGIT*MULTIPLIER
If MULTIPLIER=3 then MULTIPLIER=1 else MULTIPLIER=3 endif
end for
CHECK DIGITSTR=str (PRODUCTNO)
CHECK DIGIT=10-int (asc (right (CHECK DIGITSTR,1))-asc ('0'))
Note: This algorithm could result in the Check Digit being calculated as 10. In this instance, take the right most digit, zero, as the check digit to use in the barcode.
This looks a bit like a UPC-A check digit calculation:
If you ignore the IF isnumeric else
block then the loop basically performs this calculation (with [x]
indicating digit in position x
by starting counting from the right):
[1] * 3 + [2] + [3] * 3 + [4] + [5] * 3 ...
which is the same as ([1] + [3] + [5] + ...) * 3 + [2] + [4] + ...
So effectively:
right (CHECK DIGITSTR,1)
is basically doing)which is how the UPC-A check digit is calculated (as per link above).
Now the only oddity is that UPC-A doesn't support characters - only digits as far as I'm aware - so I'm not sure why you would need to map non-digits into digit range (that's what the else
block is doing).