%hide %latex \parindent 0pt \setlength{\parskip}{12pt} \textbf{\Large{ISBN (10 Ziffern):}} \textbf{Definition:} $$C := \lbrace{(a_1,\dots{},a_{10}) | \sum_{i=1} ^{10} i \cdot a_i \equiv 0 \mod 11\rbrace}; \qquad a_i \in \lbrace{1,\dots{},9,X\rbrace}$$ Die ersten neun Ziffern der ISBN-Nummer enthalten die Nutzdaten. Die zehnte Ziffer ist eine Prüfziffer, die sich aus einer gewichteten Quersumme der ersten neun Ziffern ergibt. $a_{10}$ wird in der obigen Definition durch Verwendung der Tatsache, dass $-1 \equiv 10 \mod 11$ ist, mit in die Summe gezogen. Falls $a_{10} = 10$, wird dies durch ein $X$ symbolisiert. In das folgende Eingabefeld kann eine ISBN-Nummer eingegeben werden. (Eingabe mit ENTER bestätigen) \begin{itemize} \item Es wird überprüft, ob es sich um eine gültige ISBN handelt. \begin{itemize} \item Genau eine falsche Ziffer wird sicher erkannt. \item Die Vertauschung zweier benachbarter Ziffern wird sicher erkannt. \end{itemize} \item Eine durch einen Stern (*) als unleserlich gekennzeichnete Ziffer wird berechnet. \\ (Höchstens eine Ziffer darf unleserlich sein.) \end{itemize} --------------------------------- nächstes Feld ------------------------------------ %hide def check_format(isbn): """ Überprüft, ob der übergebene String: - abzüglich Trennstriche 10 Zeichen enthält - Zeichen 1 bis 9 aus den Ziffern 0..9 oder '*' besteht - Zeichen 10 aus den Ziffern 0..9, 'X' oder '*' besteht - '*' höchstens einmal vorkommt (gilt als Ziffer) INPUT: isbn - eine potentielle ISBN als Zeichenkette OUTPUT: ist der String wie eine ISBN formatiert? EXAMPLES: sage: check_format('3-446-22431-9') True sage: check_format('invalid string') False """ # Entfernen der Bindestriche isbn = isbn.replace('-','') # Überprüfung der Länge if len(isbn) <> 10: return false # Überprüfung der Zeichen 1 bis 9 for i in range(9): if isbn[i] not in ('0','1','2','3','4','5','6','7','8','9','*'): return false # Überprüfung des 10. Zeichens if isbn[9] not in ('0','1','2','3','4','5','6','7','8','9','*','X','x'): return false # Anzahl der '*' korrekt? if isbn.count('*') > 1: return false return true ############################## Ausgabe ################################# def printDef (isbn, result): """ Gibt die Definition der ISBN mit den übergebenen Werten aus. (Die Funktion ist nur für Ausgabezwecke gedacht.) INPUT: isbn - ein gültiger ISBN-String result - Das Ergebnis des Terms EXAMPLES: sage: printDef ('3-446-22431-9','0') """ # Löschen der Bindestriche isbn_number = isbn.replace('-','') # Erstellen und Ausgeben des Strings outString = '$1 \cdot ' + isbn_number[0] for i in range(1,10): outString += ' + ' + str(i+1) + ' \cdot ' + str(getNumber(isbn_number[i])) html(outString + ' \equiv ' + result + ' \;mod\; 11$') ########################## Hilfsfunktionen ############################## def getNumber(ziffer): """ Liefert den passenden String für die Darstellung einer Ziffer: - '1'..'9' -> 1..9 - 'X' -> 10 - '*' -> a INPUT: ziffer - Eine Ziffer OUTPUT: Passende Zahl oder Zeichen für die Ziffer EXAMPLES: sage: getNumber('1') 1 sage: getNumber('X') 10 """ if ziffer == 'X' or ziffer == 'x': return 10 elif ziffer == '*': return 'a' else: return int(ziffer) ######################## Überprüfen der ISBN ############################# def getCheckSum(isbn): """ Nachrechnen der Prüfziffer erkennt: - Eine falsche Ziffer - Zahlendreher zweier benachbarter Ziffern INPUT: isbn - ISBN-String (optional mit Bindestrichen) OUTPUT: Das Ergebnis der gewichteten Quersumme mod 11 EXAMPLES: sage: getCheckSum('3-446-22431-9') 0 sage: getCheckSum('3-446-22431-7') 2 """ # Löschen der Bindestriche isbn_number = isbn.replace('-','') # Berechnung der Prüfziffer result = 0 for i in range(10): result += (i+1)*getNumber(isbn_number[i]) return result % 11 ###################### Berechnung einer Unbekannten ###################### def getUnknownValue (isbn): """ Eine durch einen Stern (*) als unbekannt markierte Ziffer wird berechnet. Die in der Definition angegebene Gleichung wird aufgestellt und gelöst. INPUT: isbn - ISBN-String mit höchstens einem Stern (*). (Bindestriche sind ggf. enthalten) OUTPUT: Der Zahlenwert der unbekannten Ziffer EXAMPLES: sage: getUnknownValue ('3-446-22*31-9') 4 """ # Entfernen der Bindestriche isbn = isbn.replace('-','') # Index der unbekannten Ziffer bestimmen index = isbn.find('*') # Berechnung der übrigen Werte result = 0 numbers = range(10) numbers.remove(index) for i in numbers: result += (i+1) * int(isbn[i]) # Lösung der Gleichung value = Mod(-result,11) / (index+1) # 10 -> 'X' if value == 10: return 'X' else: return value ################################################################################### # Die Benutzerschnittstelle # ################################################################################### @interact def validate_isbn(isbn=input_box(default='3-446-22431-9',label='ISBN',type=str)): if check_format(isbn) == False: html('Ungültiges Format!') else: # Ist eine unbekannte Ziffer enthalten? if isbn.count('*') == 1: value = getUnknownValue (isbn) html('Betrachte die Kongruenz: \n') printDef (isbn,'0') html('\nLösung: a = ' + str(value) ) html('\nDie vollständige ISBN lautet: ' + isbn.replace('*',str(value)) ) # Kontrollieren der Prüfziffer # (Falsche Ziffer?, Zwei benachbarte Ziffern vertauscht?) else: if getCheckSum(isbn) == 0: html('Es handelt sich um eine gültige ISBN, da \n') printDef (isbn,'0') else: html('Die ISBN enthält einen Fehler, da \n') printDef (isbn,str(getCheckSum(isbn)))