On Tue, 9 May 2017 08:24:29 -0700 (PDT), in message
<
a6126129-9f36-4069...@googlegroups.com>, Randy Gress
(
randal...@gmail.com) wrote:
> I have an AlphaNumeric Scanline that currently we use a MOD 10 check digit on.
Modulo 10 is a poor choice. You get much better cycle length if your
congruence class is of prime order.
> We recently switched companies that scans and verify these Scanlines and
> because of some issues with there scanning equipment we discovered that
> our check digit routine is not very robust (in certain cases 5 and S in
> the same position would evaluate to the same check digit).
>
> So I have been asked to research better check digit algorithms for our
> AlphaNumeric Scanline. My first thought is to use a two numeric Check
> Digit using MOD 100. But in all my searches I can't find any references
> to doing it this way. I have found some references to using a MOD 97
> check digit because it is a Prime number. But I can't find anything
> that states why that is good.
This comes from Group Theory. A cyclic group -- typically a congruence
class -- is guaranteed to have a maximum cycle length if the group is of
prime cardinality. This property is used in pseudo-random number
generation, to maximise cycle length in the stream of PRNs.
> I also found references to MOD25, MOD30 and MOD36 check digit routines
> that utilize just one character with both Alpha and Numerics used in the
> check digit.
>
> So does anyone know of a good 2 numeric Check Digit algorithm for an
> AlphaNumeric Scanline?
Here are a couple of functions I have just knocked up to generate a
single alphanumeric check digit, modulo 11, or a 2-digit check digit,
modulo 67.
=========================================================================
/* Function to generate a Modulo 11 checksum. */
(NOSIZE,NOFOFL):
MOD11:
PROC(str) RETURNS(CHAR(1)) REORDER;
DCL str CHAR(*) NONASGN INONLY;
DCL (p,check_sum) BIN FIXED(32,0) UNSIGNED INIT(0),
check_digits CHAR(11) STATIC NONASGN INIT('0123456789X'),
(LENGTH,MOD,RANK,SUBSTR) BUILTIN;
DO p = 1 UPTHRU LENGTH(str);
check_sum += RANK(SUBSTR(str,p,1));
END;
RETURN(SUBSTR(check_digits,MOD(check_sum,11)+1,1));
END MOD11;
/* Function to generate a Modulo 67 checksum. */
(NOSIZE,NOFOFL):
MOD67:
PROC(str) RETURNS(CHAR(2)) REORDER;
DCL str CHAR(*) NONASGN INONLY;
DCL (p,check_sum) BIN FIXED(32,0) UNSIGNED INIT(0),
check_digits PIC '99',
(LENGTH,MOD,RANK,SUBSTR) BUILTIN;
DO p = 1 UPTHRU LENGTH(str);
check_sum += RANK(SUBSTR(str,p,1));
END;
check_digits = MOD(check_sum,67);
RETURN(check_digits);
END MOD67;
=========================================================================
Note that these are untested, but should get you on your way to an
improved solution.
Note also that I am assuming you are using IBM Enterprise PL/I. If you
are using an older compiler you might need to adjust the syntax to cope.
--
Regards,
Dave [RLU #314465]
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
dwn...@spamtrap.ntlworld.com (David W Noon)
Remove spam trap to reply by e-mail.
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*