AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Prüfziffer für IBAN berechnen

Ein Thema von kwhk · begonnen am 12. Sep 2013 · letzter Beitrag vom 16. Sep 2013
Antwort Antwort
Amateurprofi

Registriert seit: 17. Nov 2005
Ort: Hamburg
1.111 Beiträge
 
Delphi XE2 Professional
 
#1

AW: Prüfziffer für IBAN berechnen

  Alt 12. Sep 2013, 13:43
Was in #1 nicht erwähnt wurde, ist, dass die Prüfziffern nicht 00 oder 01 sein darf.

Hier eine Funktion, die aus BLZ (8-stellig) und Kontonummer (10-stellig) eine "Deutsche" IBAN erstellt.


Delphi-Quellcode:
FUNCTION CreateGermanIBAN(Const BankCode,Account:String):String;
const csmax=(High(NativeUInt)-9) div 10;
var cs:NativeUInt; i,cc:integer; s:string;
begin
   if (Length(BankCode)<>8) or (Length(Account)<>10) then Exit('');
   s:=BankCode+Account+'131400'; // 131400 = 'DE00'
   cs:=0;
   for i:=1 to Length(s) do begin
      if cs>csmax then cs:=cs mod 97;
      cs:=cs*10+Ord(s[i])-Ord('0');
   end;
   if cs>96 then cs:=cs mod 97;
   cc:=98-cs;
   if cc<2 then inc(cc,97); // 00-->97, 01--> 98
   result:='DE00';
   result[3]:=Chr(cc div 10+Ord('0'));
   result[4]:=Chr(cc mod 10+Ord('0'));
   result:=result+BankCode+Account;
end;
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 15. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#2

AW: Prüfziffer für IBAN berechnen

  Alt 12. Sep 2013, 14:48
Dieses "csmax" kann man sich schenken.
Bei der Modulo-Arithmetik rechnet man einfach nach jeder Operation mit mod 97 :
Delphi-Quellcode:
FUNCTION CreateGermanIBAN(Const BankCode,Account:String):String;
var cs, i,cc:integer; s:string;
begin
   if (Length(BankCode)<>8) or (Length(Account)<>10) then Exit('');
   s:=BankCode+Account+'131400'; // 131400 = 'DE00'
   cs:=0;
   for i:=1 to Length(s) do begin
      cs:=(cs*10+Ord(s[i])-Ord('0')) mod 97;
   end;
   cc:=98-cs;
   if cc<2 then inc(cc,97); // 00-->97, 01--> 98
   result:='DE00';
   result[3]:=Chr(cc div 10+Ord('0'));
   result[4]:=Chr(cc mod 10+Ord('0'));
   result:=result+BankCode+Account;
end;
fork me on Github
  Mit Zitat antworten Zitat
Amateurprofi

Registriert seit: 17. Nov 2005
Ort: Hamburg
1.111 Beiträge
 
Delphi XE2 Professional
 
#3

AW: Prüfziffer für IBAN berechnen

  Alt 12. Sep 2013, 23:02
Dieses "csmax" kann man sich schenken.
Bei der Modulo-Arithmetik rechnet man einfach nach jeder Operation mit mod 97 :
Delphi-Quellcode:
FUNCTION CreateGermanIBAN(Const BankCode,Account:String):String;
var cs, i,cc:integer; s:string;
begin
   if (Length(BankCode)<>8) or (Length(Account)<>10) then Exit('');
   s:=BankCode+Account+'131400'; // 131400 = 'DE00'
   cs:=0;
   for i:=1 to Length(s) do begin
      cs:=(cs*10+Ord(s[i])-Ord('0')) mod 97;
   end;
   cc:=98-cs;
   if cc<2 then inc(cc,97); // 00-->97, 01--> 98
   result:='DE00';
   result[3]:=Chr(cc div 10+Ord('0'));
   result[4]:=Chr(cc mod 10+Ord('0'));
   result:=result+BankCode+Account;
end;
Ja, mit der Folge dass man etwa 10 Mal soviel Mod Operationen braucht.
Mag sein, dass sich das nicht gewaltig auswirkt, aber ich denke man sollte immer auch auf die Performance achten.
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat
Benutzerbild von BUG
BUG

Registriert seit: 4. Dez 2003
Ort: Cottbus
2.094 Beiträge
 
#4

AW: Prüfziffer für IBAN berechnen

  Alt 13. Sep 2013, 00:22
Ja, mit der Folge dass man etwa 10 Mal soviel Mod Operationen braucht.
Allerdings sind Sprünge (wie im if) auch nicht das Wahre, insbesondere bei Pipeline-Prozessoren. Zudem sind Divisionen heute auch nicht mehr so teuer, wie sie mal waren.
Im Zweifelsfall müsste man ausmessen, was schneller ist (eventuell abhängig von der Branch-Prediction/Speculative-Execution des Prozessors).

Bei dieser Funktion gibt es noch andere Dinge zu optimieren. Zum Beispiel ist die Speicherallokation für den temporären String nicht unbedingt billig. Auch den Rückgabewert könnte man vielleicht effizienter Zusammenbasteln.
Ansonsten kann man überlegen, nach wie vielen Stellen man jeweils frühestens einmal modulo 97 rechnen muss und dann die Schleife entsprechen aufteilen.

Und dann ist da noch die Frage, ob sich der Optimierungsaufwand überhaupt lohnt. Schließlich ist die Geschwindigkeit dieser Funktion nur bedeutsam, wenn man sie auf sehr vielen Nummern ausführen will, wobei es dann vermutlich eher an den IO-Operationen hängt.
  Mit Zitat antworten Zitat
Amateurprofi

Registriert seit: 17. Nov 2005
Ort: Hamburg
1.111 Beiträge
 
Delphi XE2 Professional
 
#5

AW: Prüfziffer für IBAN berechnen

  Alt 13. Sep 2013, 01:01
Ja, mit der Folge dass man etwa 10 Mal soviel Mod Operationen braucht.
Allerdings sind Sprünge (wie im if) auch nicht das Wahre, insbesondere bei Pipeline-Prozessoren. Zudem sind Divisionen heute auch nicht mehr so teuer, wie sie mal waren.
Im Zweifelsfall müsste man ausmessen, was schneller ist (eventuell abhängig von der Branch-Prediction/Speculative-Execution des Prozessors).

Bei dieser Funktion gibt es noch andere Dinge zu optimieren. Zum Beispiel ist die Speicherallokation für den temporären String nicht unbedingt billig. Auch den Rückgabewert könnte man vielleicht effizienter Zusammenbasteln.
Ansonsten kann man überlegen, nach wie vielen Stellen man jeweils frühestens einmal modulo 97 rechnen muss und dann die Schleife entsprechen aufteilen.

Und dann ist da noch die Frage, ob sich der Optimierungsaufwand überhaupt lohnt. Schließlich ist die Geschwindigkeit dieser Funktion nur bedeutsam, wenn man sie auf sehr vielen Nummern ausführen will, wobei es dann vermutlich eher an den IO-Operationen hängt.
Willst du jetzt ernsthaft darüber diskutieren, ob der durch das IF verursachte Sprung mehr Zeit kostet als ein MOD ?

Selbstverständlich hast du Recht, dass man das noch erheblich optimieren kann.
Du sagst "müsste man ausmessen", "kann man überlegen",
Miss es doch und überleg es mal und dann schreibe die optimale Funktion.
Da wären Dir einige Leute dankbar.

Mein Ziel war nicht, eine "superperformante" Funktion zu zeigen, ich habe schlicht und einfach einen Code aus einem bestehenden Projekt kopiert. http://www.delphipraxis.net/170138-i...ml#post1228268
Dann wurde eine "Optimierung" gezeigt, die (auf meinem Rechner) etwa 65% mehr Zeit braucht.
Entsprechend habe ich reagiert.
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 15. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#6

AW: Prüfziffer für IBAN berechnen

  Alt 13. Sep 2013, 05:10
Bei der Erzeugung von IBANs ist etwas wichtiger als alles Andere: Korrektheit.
Das Ding muss richtig rechnen; das hat oberste Priorität.
Nichts ist schlimmer als wenn in einer Produktivumgebung tausende falsche IBANs verschickt werden.

Daher muss man so vorgehen:
Schritt 1:
Testdaten besorgen und eine Testumgebung für die IBAN-Funktion aufbauen.
Man sollte mindestens 5 versch. IBANs testen.
Dazu kann man ein kleines Testprogramm schreiben oder man verwendet DUnit.
Man könnte auch nur mit Assert-Anweisungen arbeiten; Hauptsache es gibt Tests.
Nicht nur die Gut-Fälle testen sondern auch gezielt ungültige Daten übergeben die von der IBAN-Funktion abgewiesen werden müssen.

Schritt 2:
Umsetzen der IBAN Berechnung in Code.
Dabei sollte man gleich alle Länder vorsehen.
Ausserdem gehört dazu auch eine Prüfung der Eingabeparameter (Buchstaben in Konto-Nr, ...).

Schritt 3:
Optional prüfen, ob man den Code noch optimieren kann.
Wichtig ist, dass man mit dem Optimieren aufhört bevor der Code schlecht lesbar wird.
Einfacher Code ist meist auch schneller (bzw. ausreichend schneller) Code.
Nach jedem Optimierungsschritt muss auf Korrektheit getestet werden.
fork me on Github

Geändert von sx2008 (13. Sep 2013 um 05:12 Uhr)
  Mit Zitat antworten Zitat
Furtbichler
(Gast)

n/a Beiträge
 
#7

AW: Prüfziffer für IBAN berechnen

  Alt 13. Sep 2013, 06:41
Korrektheit...das hat oberste Priorität.
Richtig. Nagel auf den Kopf und den Punkt getroffen.
Klitzekleines aber:
Zitat:
Man sollte mindestens 5 versch. IBANs testen.
Wenn, dann richtig: Stichwort: Codeabdeckung. Die Tests müssen in diesem Falle wirklich alle Fälle abdecken, d.h. (ich hab nu nich in den Code geschaut) es müssen Äquivalenzklassen gebildet werden, das sind die Mengen von Eingaben, die den jeweils gleichen Codepfad durchlaufen. Und aus jeder der Äquivalenzklassen reicht es, 1-3 Kandidaten zu nehmen.

Gibt es Übergänge zwischen den Äquivalenzklassen (z.B. <0, =0, >0), nimmt man sich jeweils Kandidaten 'am Rand', also die, die gerade noch in eine Klasse passen.

Bei gutem Code benötigt man dann keine gezielten 'Angriffe' mit ungültigen Daten, denn diese sind in einer oder mehrerer Äquivalenzklassen enthalten. Trotzdem...
Nicht nur die Gut-Fälle testen sondern auch gezielt ungültige Daten übergeben die von der IBAN-Funktion abgewiesen werden müsssen...Nach jedem Optimierungsschritt muss auf Korrektheit getestet werden.
Ja, ja, ja. Abnick, full ACK, und was man sonst noch so alles sagt.

Das sollte man eigentlich für jede Klasse machen, aber wer hat schon die Zeit dafür (ja: man muss sie sich nehmen).
  Mit Zitat antworten Zitat
Benutzerbild von kwhk
kwhk

Registriert seit: 25. Mär 2009
Ort: Dresden
168 Beiträge
 
Delphi 10.3 Rio
 
#8

AW: Prüfziffer für IBAN berechnen

  Alt 12. Sep 2013, 15:24
Was in #1 nicht erwähnt wurde, ist, dass die Prüfziffern nicht 00 oder 01 sein darf.
Ich hatte gesagt: der Rest aus MOD97 = 00..96 / PZ = 98 - Rest
Damit kann die PZ nur 02..96 sein, also keine 00 und 01
@sc2008, Deine Methode ist natürlich sehr kompakt.
if cc<2 then ... ist m.E. nicht erforderlich, weil bei mod 97 nur 00 bis 96 herauskommen kann.
Und deshalb 98-cs niemals <2 werden kann (deshalb haben die Erfinder dieser Formel gesagt "98-2").

Ich hätte mir gewünscht, dass jemand einen Weg kennt, wie man auch mit langen Zahlen richtig rechnen kann.
Bei mod97 mag das ja so angehen. Im alten Turbo-Pascal war ja REAL eine reine Software-Zahlendarstellung.
Später kamen dann die Numeric-Prozessoren und deren Zahlenformate dazu.
Da nicht jeder PC automatisch einen Numeric-Prozessor hatte (erst ab 386 / 486), musste, wenn der fehlte, ebenfalls eine Softwarelösung die Bearbeitung dieser Zahlendarstellungen übernehmen.
Man könnte doch eine Software-Darstellung wählen, die lange Integerzahlen erlaubt.
Wenn ich z.B. COBOL nehme, dann ist dort das Zahlenformat, wie auf dem IBM-Host (Großrechner).

http://www.3480-3590-data-conversion...ed-fields.html

Da kann ich z.B. das gepackte Format wie beim Host benutzen. Das macht alles die COBOL-Laufzeitbibliothek.
Es ist damit kein Problem eine 24-stellige Dezimalzahl / 97 zu dividieren.
Bei den heute so schnellen CPUs spielt dieser interne Aufwand, der notwendig ist, um das zu realisieren, doch kaum eine Rolle.
Was PC-COBOL kann, sollte doch in Pascal und C auch möglich sein.
Natürlich könnte man sich eigene Zahlendarstellungen und zugehörige Functionen basteln.
Hartmut

Geändert von kwhk (12. Sep 2013 um 16:02 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Union
Union

Registriert seit: 18. Mär 2004
Ort: Luxembourg
3.492 Beiträge
 
Delphi 7 Enterprise
 
#9

AW: Prüfziffer für IBAN berechnen

  Alt 12. Sep 2013, 20:12
So was gibt's ja http://bigint-dl.sourceforge.net/
Ibi fas ubi proxima merces
sudo /Developer/Library/uninstall-devtools --mode=all
  Mit Zitat antworten Zitat
Amateurprofi

Registriert seit: 17. Nov 2005
Ort: Hamburg
1.111 Beiträge
 
Delphi XE2 Professional
 
#10

AW: Prüfziffer für IBAN berechnen

  Alt 12. Sep 2013, 22:57
Was in #1 nicht erwähnt wurde, ist, dass die Prüfziffern nicht 00 oder 01 sein darf.
Ich hatte gesagt: der Rest aus MOD97 = 00..96 / PZ = 98 - Rest
Damit kann die PZ nur 02..96 sein, also keine 00 und 01
@sc2008, Deine Methode ist natürlich sehr kompakt.
if cc<2 then ... ist m.E. nicht erforderlich, weil bei mod 97 nur 00 bis 96 herauskommen kann.
Und deshalb 98-cs niemals <2 werden kann (deshalb haben die Erfinder dieser Formel gesagt "98-2").
Recht hast Du.
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:31 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz