Search code examples
barcodechecksum

Is this a recognised checksum algorithm?


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.


Solution

  • 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:

    1. Sum up all digits in odd positions and multiply by 3
    2. Sum up all digits in even positions
    3. Build the sum of step 1 and 2
    4. Get modulo 10 of step 3 (that what right (CHECK DIGITSTR,1) is basically doing)
    5. Subtract the modulo of 10

    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).