if 0 {[Richard Suchenwirth] 2002-12-15 - Unique item identifiers may at times get pretty lengthy, especially if numeric. For instance, an EAN code (European Article Number) as found on many food and non-food articles, is 13 digits long. In the typical scanning of barcodes, or occasional typing by hand, errors may occur that can be detected by requesting a certain property from the code - most often that a check sum computed by some rules, modulo a number, gives zero. Albrecht Beutelspacher's ''Pasta all'infinito'' (M�nchen: dtv 2002) taught me some rules, amid much other reading pleasure (highly recommended if you're interested in Math and/or Italy), so here's my Tcl implementations which return 1 if the input code is valid, else 0. Digits in the EAN code enter the checksum weighted alternatingly by 1 or 3. Let's take for example the EAN of that book: EAN: 9 7 8 3 4 2 3 3 3 0 6 9 5 weight: 1 3 1 3 1 3 1 3 1 3 1 3 1 gives: 9+21+8+9+4+6+3+9+3+0+6+27+5 = 110, 110 % 10 = 0 -> ok } proc EANvalid ean { regsub -all {[^0-9]} $ean "" ean ;# remove all non-digits set weight 1 set sum 0 foreach digit [split $ean ""] { set sum [expr {$sum + $digit * $weight}] set weight [expr {$weight == 1? 3: 1}] } expr {($sum % 10) == 0} } if 0 {This procedure detects all 1-digit errors, but may fail on 10% of digit swaps (e.g. if 3 8 was typed instead of 8 3). A more robust scheme is used in ISBN (International Standard Book Numbers), ten-digit sequences consisting of the following fields: country publisher number checkdigit, e.g. 3 (Germany) 423 (dtv) 33069 4 Weights in this scheme decrease from 10 to 1, and the special twist is that the check digit is "undecimal", meaning both "non-decimal" (because besides the digits 0-9, it may be X) and "base 11" (Latin ''undecem'', X standing for 10). For example, an elderly book that I also really like has the ISBN ISBN: 3 - 5 4 0 - 1 0 3 5 2 - X weight: 10 9 8 7 6 5 4 3 2 1 gives: 30+ 45+32+0+ 6+0+12+15+4+ 10 = 154, 154%11 = 0 -> ok } proc ISBNvalid isbn { regsub -all {[^0-9X]} $isbn "" isbn set weight 10 set sum 0 foreach digit [split $isbn ""] { if {$digit=="X"} {set digit 10} set sum [expr {$sum + $digit * $weight}] incr weight -1 } expr {($sum % 11) == 0} } if 0 {Note also that modern books have a bar-coded EAN which, after the prefix 978, contain the ISBN minus its check digit (EAN is decimal, so X might be a problem), and adding the EAN check digit, so the Beutelspacher book has the EAN 978 3 423 33069 5 ISBN: 3-423-33069-4 See also [UIC vehicle number validator] and [Validating Credit Card Check Digits] ---- [Category Concept] | [Arts and crafts of Tcl-Tk programming] }