Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

append check digits

Status
Not open for further replies.

gfrlaser

Programmer
May 24, 2007
67
US
Has anyone written a routine I could use to calculate and append a check digit to a 14 character alpha numeric string?

I believe a mod 10 routine for 128 barcodes is what I am looking for. I wondered also if I am limited to a set number of characters using mod 10. I have scoured the internet with no real good results. Any suggestions where to look is appreciated.

Thanks to all

And of course HAPPY NEW YEAR!!

Will
 
SYS(2007) will generate a 16 or 32 bit checksum. This returns the checksum as a string so if you really do only need a single digit then try something like:

Code:
?Left(SYS(2007, "123test"), 1)


Geoff Franklin
 
I didnt think anything that easy would work! So if my data contains a field bnum with "F6X32K3AA"...
replace field chk with Left(SYS(2007,bnum),1) will give me a valid check digit, right? Its critical I am right about this.
Thanks for your reply. Happy new year!!
 
will give me a valid check digit, right?

I don't know what's "valid" in your context but Sys(2007) returns string of digits and you'll get a single digit if you take the single leftmost character. The value will be repeatable - you'll always get the same digit for the same input string - but I suspect you'll get an uneven distribution of digits.

It's a 16-bit checksum so values will be below 65535 and you'll see 1,2,3,4,5 and 6 more often than you'll see 7, 8 and 9. And I now realise you'll never see 0 - the checksum will never start with zero. Use Right() to take the final digit rather than the first one.

Geoff Franklin
 
You can't do a mod 10 on a code with letters, mod 10 is applied to a number, and it's really simply the last digit of that number, so mod 10 is not a good choice for a check digit.

EAN13 barcodes, which have a 13th check digit do compute mod 10, but it's not applied on the net 12 digit number before the check digit, because that would mean the 13th digit would simply copy the 12th.

The algorithm for the check digit is calculating a sum of the digits, each odd digit (1st, 3rd etc) is multiplied by 3 - this helps to find out if there is a typing eror/turner. But again this only works on digits, not letters. You might use the ascii codes of the letters instead, eg calculate the following would be a solution:

Code:
Function checkdigit()
   LParameters tcCode
   
   Local lnCount, lnChecksum
   lnChecksum = 0 && could also initialise differently 
   For lnCount = 1 To Len(tcCode)
       lnChecksum = lnChecksum + ASC(Substr(tcCode,lnCount,1))*(1+2*lnCount%2)
   Endfor lnCount

   Return lnChecksum%10

This check digit would be an additional digit, so either you create a net code of 9 digits plus this check digit or you add it as an 11th digit to the 10 digit code generated earlier. When checking entered codes you'd use one digit less then entered, calculate this digit and verify with the last entered digit.

All in all I think you are asked to apply a certain standard and you should know best what kind of EAN or MSI, CCN, Code39, Code93 or other barcode you should support and then look for official algorithms to generate these and their checksums.

Bye, Olaf.
 
I see. Thanks. The 128C is the barcode most likely to be used in this project.
 
128C is for numeric only (you say alpha numeric in your original question), and then only when the number of digits is even, e.g. 14 digits, 16 digits.
128C achieves a very compact code as it encodes the digits in pairs. If the first digit is 2, and the second is 3, then these are encoded as 23 which gives good compression.
 
[ ]

I don't know if the following code will do what you want or meet any specs that you need to adhere to. However, it might give you some ideas on creating check digits.

I use this to create check digits for part numbers using a base 30 modulus. By changing various things like the modulus or the multiplier to suit, this could be used to create relatively secure check codes.

Also, you might think about putting your check digit(s) WITHIN the generated number rather than at the end. Since it would look just like the rest of the number it would be very hard to tell which are the check digits and which are not.

[tt]
*******************
*
* FUNCTION NAME: Genckcode
*
*******************
*
* Generates check code suffix for any string of numbers/letters.
* Calculates check code on entry string which must be in the
* correct case and length upon entry.
*
* SYNTAX:
* = Genckcode(qStr)
*
* ENTRY:
* qStr = CN: String needing check code
*
* EXIT:
*
* RETURNs:
* = C: Two digit UPPER case check code
*
*******************

FUNCTION Genckcode
PARAMETERS qStr

zchk = 0
zmult = 1
FOR z = 1 TO LEN(qStr)
zchr = SUBSTR(qStr, z, 1)
IF ISALPHA(zchr) OR ISDIGIT(zchr)
zchk = zchk + zmult * ASC(zchr) && zchk is a sum
zmult = IIF(zmult = 1, 2, 1)
ENDIF
ENDFOR

zmult = Genckchr(zchk) && Get second character

zchk = ALLTRIM(STR(zchk)) && Get first character
zchr = 0
FOR z = 1 TO LEN(zchk)
zchr = zchr + ASC(SUBSTR(zchk, z, 1)) - 48
ENDFOR

zchr = Genckchr(zchr) && Get first character

zchr = zchr + zmult

RETURN zchr


*******************
*
* FUNCTION NAME: Genckchr
*
*******************
*
* Generates one character from raw mod 30 number.
*
* SYNTAX:
* = Genckchr(qNum)
*
* ENTRY:
* qNum = N: Number to convert to character
*
* EXIT:
*
* RETURNs:
* qNum = C: Upper case alpha/numeric character
*
*******************

FUNCTION Genckchr
PARAMETERS qNum

qNum = MOD(qNum, 30) + 48 && Get character
DO CASE
CASE qNum > 71
qNum = qNum + 12 && 'S' not allowed
CASE qNum > 68
qNum = qNum + 11 && 'O' not allowed
CASE qNum > 63
qNum = qNum + 10 && 'I' not allowed
CASE qNum > 59
qNum = qNum + 9 && 'D' not allowed
CASE qNum > 58
qNum = qNum + 8 && 'B' not allowed
CASE qNum > 57
qNum = qNum + 7 && skip format characters
ENDCASE

RETURN UPPER(CHR(qNum))
[/tt]


mmerlinn


"We've found by experience that people who are careless and sloppy writers are usually also careless and sloppy at thinking and coding. Answering questions for careless and sloppy thinkers is not rewarding." - Eric Steven Raymond
 
[ ]

I forgot to mention that the characters in the returned check code generated by the above program code can contain any numerical digit and/or any upper case alpha character except 'B', 'D', 'I', 'O', 'S', & 'Z'.

If you change the modulus to more than 30, then you must modify the character list to compensate. If changed to less than 30, then it will work fine but with a shorter alpha character set. Changing the modulus to 10 will return only numerical check digits.

mmerlinn


"We've found by experience that people who are careless and sloppy writers are usually also careless and sloppy at thinking and coding. Answering questions for careless and sloppy thinkers is not rewarding." - Eric Steven Raymond
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top