Prüfziffer, Barcode
Analog zu den Teilbarkeitsregeln existiert für die wohlbekannten Barcodes, zum Beispiel auf Verpackungen, ein Prüfverfahren.
Bezahlt man in einem Geschäft seine Ware, so wird der Preis in aller Regel nicht von Hand eingegeben. Vielmehr wird der Strichcode, der sich auf jedem Artikel befindet, eingescannt. Selbst wenn dies aufgrund technischer Probleme nicht funktioniert, gibt der Kassierer nicht den Preis, sondern die zum Strichcode gehörende Ziffernfolge ein. Wie kommt es, dass ein Fehler beim Eingeben des Barcodes fast immer auffällt? Fallen Fehler wirklich immer auf?
Man braucht also eine Idee, wie man Fehler bei der Eingabe mit hoher Wahrscheinlichkeit bemerken kann – und diese Idee heisst Redundanz. Man hängt an den Teil des Codes, den man zur Identifikation des Produkts braucht, zusätzliche (redundante) Ziffern an, deren einziger Sinn es ist, den Code fehlerresistenter zu machen. Dabei sollten möglichst wenige zusätzliche Ziffern eine möglichst hohe Sicherheit bieten. Weshalb und wie man das mit nur einer Ziffer erreichen kann, hat mit Modulo-Arithmetik zu tun. Ähnliche Verfahren werden auch bei Kreditkarten, ISBN-Nummern, Seriennummern von Geldscheinen etc. verwendet.
Prüfziffer (Checksum)
Als kleines Beispiel betrachten wir das alte ISBN-System (International Standard Book Number). Dieses ist zwar nicht mehr aktuell, aber für unsere Zwecke instruktiver und einfacher verständlich als die inzwischen verwendete Variante. Die hier betrachteten Überlegungen gelten grundsätzlich auch für die meisten neueren Verfahren.
Zur Einordnung: Jedem Buch ist zur eindeutigen Identifikation eine zehnstellige ISBN-Nummer zugeordnet. Von diesen Ziffern sind die ersten die eigentliche Information; die zehnte ist eine Prüfziffer. Diese Prüfziffer, auch Checksum genannt, soll eine gewisse Sicherheit zur Vermeidung von Tipp- und Übertragungsfehlern gewährleisten.
Wir nehmen als Beispiel das Buch
P. Hartmann, Mathematik für Informatiker, Vieweg, 2003. mit der (alten) ISBN-Nummer
3-8348-0096-1.
Dabei steht die erste Ziffer für die Länder- oder Sprachgruppe, die zweite Zifferngruppe für den Verlag und die dritte für die vom Verlag vergebene Titelnummer. Die 10. Ziffer, die 1, ist die Prüfziffer.
Eine ISBN-Nummer sei mit
bezeichnet. Dabei ist für und die Prüfziffer berechnet sich gemäss:
Dies ergibt für einen Wert zwischen und . Falls das Ergebnis lautet, schreibt man dafür römisch X.
Natürlich kann man nicht erwarten, dass so alle Fehler erkannt werden. Aber, wie wir gleich sehen werden, schützt diese Prüfziffer vor den alltäglichsten Fehlern.
Ziffer fehlerhaft eingetippt
Geschieht der Fehler in der Prüfziffer selbst, dann ist der Fall klar. Wir können also den Fehler zwischen den Stellen und annehmen und müssen zeigen, dass die Prüfziffer falsch ist. Sei also
die fehlerhafte ISBN mit dem Fehler an der -ten Stelle, . Die Prüfziffer wäre so
Wir haben aber und es gilt
Wegen ist und wegen auch . Daraus folgt mit einer nicht ganz trivialen Überlegung, dass . Dabei ist die Wahl des Moduls wichtig. Entscheidend für die letzte Folgerung ist, dass eine Primzahl ist, denn für diese haben wir
Sind prim und mit , so gilt oder .
Proof
Wir brauchen die Negation des obigen Satzes:
Teilt weder noch , dann teilt auch nicht .
Wenn weder noch teilt, dann kommt nicht in der Primfaktorzerlegung von und vor, also auch nicht in der Primzahlzerlegung des Produkts . Das heisst teilt nicht.
Damit ist gezeigt, dass insbesondere für der letzte Schritt gilt und damit die Prüfziffer der ISBN eine fehlerhafte Ziffer erkennt.
Früher wurde für die Buchklassifikation anstelle der heute gebräuchlichen ISBN13- die ISBN10-Nummer verwendet. Diese beiden Nummern unterscheiden sich nur durch das Präfix und die Prüfziffer, die restlichen Ziffern stimmen überein. Ich habe mich in diesem Beispiel für die ISBN10 entschieden, da sie rechnerisch etwas handlicher ist.
Das Buch Mathematik für Informatiker hat die ISBN-10 Nummer 3-8348-0096-1, wobei die letzte Ziffer, 1, als Prüfziffer (Checksum) fungiert. Diese letzte Ziffer wird in der ISBN10-Variante aus den vorangehenden Ziffern wie folgt berechnet:
a) Überprüfe, ob die Checksum 1 korrekt ist.
b) Wähle eine beliebige Position in der ISBN-Nummer aus und vertippe dich (absichtlich). Berechnen nun die Prüfziffer der "vertippten" Nummer.
c) Angenommen, man vertippe sich an genau Stellen, sagen wir Positionen und . Registriert die Prüfziffer die Vertipper? Finde ein Beispiel für einen "Doppelvertipper", der nicht erkannt wird.
Solution
a) Es ist
b) Wenn ich mich zum Beispiel an der Stelle vertippe, , dann kriege ich als Checksum .
c) Wenn man sich an den Stellen und vertippt, dann hat man als Differenz der Checksums
Nun probiert man für , , , alle Kombinationen aus, die ergeben. Denn in diesem Fall werden die Vertipper nicht bemerkt. Das ist im Allgemeine aufwändig und von den konkreten Ziffern abhängig. Für die vorliegende Nummer klappt dies beispielsweise für , da .
All die Erkennung der "einfachen" Vertipper würde nicht funktionieren, wenn wir anstelle von beispielsweise als Modul verwendet hätten. Denn wegen , also würde etwa ein Fehler an der -ten Stelle nicht erkannt, wenn die fehlerhafte Ziffer um von der korrekten Ziffer abweicht. Die Prüfziffer Modulo bliebe dann unverändert.
Schreibe eine Python-Funktion, die zu gegebenem Input einer ISBN10-Nummer als Output angibt, ob die Nummer korrekt ist oder nicht.
Verwende anschliessend das Programm, um zu testen, dass die Prüfziffer bemerkt, falls man zwei Ziffern vertauscht hat.
Solution
Ein Beispiel ist
def isbncheck(isbnnr):
# Einzelne Ziffern aus der Nummer listen
isbnls = [int(num) for num in str(isbnnr)]
summod = 0
# Ziffern gewichten, zusammenzaehlen und mod 11 rechnen
for k in range(1,10):
summod = (summod + (k)*isbnls[k-1]) % 11
# Checksum vergleichen mit Pruefziffer
if summod == isbnls[9]:
return print("ok")
else:
return print("bärääh")
Robuster und ausführlicher wäre:
# Akzeptiert einen String, der Bindestriche ignoriert
def is_isbn10_valid(isbn_str):
# Entfernt mögliche Bindestriche und Leerzeichen
digits = isbn_str.replace("-", "").replace(" ", "")
if len(digits) != 10:
return False
# Prüfen, ob alle Zeichen (ausser evtl. 'X' am Ende) Ziffern sind
if not digits[:9].isdigit():
return False
checksum = 0
for i in range(9):
checksum += (i + 1) * int(digits[i])
# Prüfziffer validieren (kann 'X' sein)
last_char = digits[9].upper()
if last_char == 'X':
correct_checksum = 10
elif last_char.isdigit():
correct_checksum = int(last_char)
else:
return False # Ungültiges Zeichen an letzter Stelle
return (checksum % 11) == correct_checksum
# -- So würde man die Funktion verwenden --
my_isbn = "3-8348-0096-1"
if is_isbn10_valid(my_isbn):
print(f"Die ISBN '{my_isbn}' ist gültig! ✔️")
else:
print(f"Die ISBN '{my_isbn}' ist fehlerhaft. ❌")
Zahlenvertauscher
Die ISBN erkennt nicht nur einzelne fehlerhafte Ziffern, sondern auch den am häufigsten auftauchende Fehlertyp: das Vertauschen zweier aufeinanderfolgender Ziffern. In der Tat erkennt die Prüfziffer sogar Vertauschen von nicht unmittelbar aufeinanderfolgenden Ziffern, was zwar weniger vorkommt, aber für den folgenden Beweis ohne Mehraufwand mit einbezogen werden kann.
Teste einen Zahlendreher anhand von 3-8348-0069-0.
Solution
Brauche dein Python-Programm von oben.
Zeige, dass obige Checksum einen Vertauscher bemerkt. Zeige dies für Ziffern, die nicht zwingend aufeinander folgen.
Solution
Seien mit die vertauschten Positionen. Die involvierten Ziffern unterschieden sich natürlich auch, , da sonst der Vertauscher gar nicht bemerkt würde. Betrachten Sie die korrekte, , versus die inkorrekte, , Checksum. Die Differenz ist
wobei man beim letzten Schritt gleich argumentiert wie im vorangegangenen Beweis: teilt die Primzahl weder den einen noch den andern Faktor, dann sicher auch nicht das Produkt; also teilt nicht und damit unterscheiden sich die Prüfziffern Modulo .
Wie oben gesehen, ist also die Wahl des Moduls entscheidend. Bei informationstragenden Ziffern braucht man also eine Primzahl grösser oder gleich , und ist dafür die kleinstmögliche Wahl.
Bei der ISBN13 berechnet sich die Prüfziffer via

Überprüfe die Korrektheit der ISBN13 Prüfziffer.
Hier kann man noch für die oben verwendete ISBN10 die zugehörige ISBN13 Checksum nachrechnen:

Solution
Wir berechnen zuerst die gewichtete Summe:
Nun berechnen wir den Modulo 10 der Summe: . Die Prüfziffer ist dann:
Das Ergebnis 8 stimmt mit der Prüfziffer der ISBN überein.