Autor |
Beitrag |
mtm
      
Beiträge: 64
Windows 10 Pro 64 Bit
Delphi XE 6
|
Verfasst: Fr 06.09.13 17:07
Hallo zusammen,
ich habe im Netz zwar schon mal rumgeschaut aber irgendwie nichts passendes gefunden (vielleicht bin ich einfach zu dämlich). Ich möchte mit einer 24-stelligen ganzzahligen Zahl eine Modulo-Division durchführen.
Leider stoße ich dabei auf das Problem, daß die Zahl natürlich nicht in eine Integer-Variable passt und Modulo mit einem anderen Datentypen nicht funzt.
kurze Info : Ich bin dabei, mir testweise ein Programm zu schreiben, mit dem ich die IBAN von deutschen Konten berechnen kann.
Vielleicht hat da ja jemand von Euch eine Lösung
Danke im Voraus
mtm
|
|
FinnO
      
Beiträge: 1331
Erhaltene Danke: 123
Mac OSX, Arch
TypeScript (Webstorm), Kotlin, Clojure (IDEA), Golang (VSCode)
|
Verfasst: Fr 06.09.13 17:20
Moin,
selbst bauen.
Delphi-Quelltext 1: 2: 3: 4:
| function mod(a,b : double) : double; begin result := frac(a/b)*b; end; |
|
|
jfheins
      
Beiträge: 918
Erhaltene Danke: 158
Win 10
VS 2013, VS2015
|
Verfasst: Fr 06.09.13 17:41
Zu kurz gedacht
Double hat nur 16 Stellen, das Ergebnis wird also falsch sein.
Entweder mit strings arbeiten, einen vorhandenen Algo suchen oder etwas in Modulare Arithmetik einlesen
Ohne Gewähr, aber ich habe mal schnell geschaut:
(a*b + c) mod n = (a mod n) * (b mod n) + (c mod n)
Edit: Das Endergebnis natürlich wieder mod n. Die komplette, richtige Formel ist weiter unten.
Du kannst also deine 24 stellige Zahl in viele kleinere Abschnitte teilen (z.B. 4 Teile à 6 Ziffern) und dann hast du für b Terme wie 10^0, 10^6, 10^12 und 10^18. Die Ergebnisse von den vier (b mod n) Termen kannst du also vorher ausrechnen. Der Rest ist einfache Integer-Mathematik.
Zuletzt bearbeitet von jfheins am Sa 07.09.13 16:19, insgesamt 1-mal bearbeitet
Für diesen Beitrag haben gedankt: Martok
|
|
Mathematiker
      
Beiträge: 2622
Erhaltene Danke: 1447
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: Fr 06.09.13 17:52
Hallo,
folgender Text testet die Korrektheit einer IBAN-Nummer:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51:
| procedure CheckIBAN; Var iban: string; function ChangeAlpha(const input: string): string; var a: Char; begin Result := input; for a := 'A' to 'Z' do begin Result := StringReplace(Result, a, IntToStr(Ord(a) - 55), [rfReplaceAll]); end; end; function CalculateDigits(iban: string): Integer; var v, l, rest, number: Integer; alpha: string; begin iban := UpperCase(iban); if Pos('IBAN', iban) > 0 then Delete(iban, Pos('IBAN', iban), 4); iban := iban + Copy(iban, 1, 4); Delete(iban, 1, 4); iban := ChangeAlpha(iban); v := 1; l := 9; rest := 0; alpha := ''; try while v <= Length(iban) do begin if l > Length(iban) then l := Length(iban); alpha := alpha + Copy(iban, v, l); number := StrToInt(alpha); rest := number mod 97; v := v + l; alpha := IntToStr(rest); l := 9 - Length(alpha); end; except rest := 0; end; Result := rest; end; begin iban:=edit1.text; iban := StringReplace(iban, ' ', '', [rfReplaceAll]); if CalculateDigits(iban) = 1 then else end; |
Der Quelltext muss einfach etwas umgebaut werden.
Beste Grüße
Mathematiker
_________________ Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
|
|
mandras
      
Beiträge: 431
Erhaltene Danke: 107
Win 10
Delphi 6 Prof, Delphi 10.4 Prof
|
Verfasst: Fr 06.09.13 20:18
jfheins hat folgendes geschrieben : |
(a*b + c) mod n = (a mod n) * (b mod n) + (c mod n)
|
Definitiv nicht:
(a*b + c) mod n ist stets < n,
allein (a mod n) * (b mod n) kann schon bis zu (n-1)^2 werden
|
|
Marc.
      
Beiträge: 1876
Erhaltene Danke: 129
Win 8.1, Xubuntu 15.10
|
Verfasst: Sa 07.09.13 14:54
mandras hat folgendes geschrieben : | jfheins hat folgendes geschrieben : |
(a*b + c) mod n = (a mod n) * (b mod n) + (c mod n)
|
Definitiv nicht:
(a*b + c) mod n ist stets < n,
allein (a mod n) * (b mod n) kann schon bis zu (n-1)^2 werden |
Stimmt! Er hat ein mod n vergessen: Wiki: Modulo Equivalencies.
Es ist nämlich nach korrekter Anwendung der Identäten und des Distributivgesetzes:
Quelltext 1: 2:
| (a*b + c) mod n = ((((a mod n)*(b mod n) mod n) mod n) + (c mod n)) mod n = (a mod n) * (b mod n) mod n + (c mod n) |
Beste Grüße
|
|
Mathematiker
      
Beiträge: 2622
Erhaltene Danke: 1447
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: Sa 07.09.13 15:05
Hallo,
Marc. hat folgendes geschrieben : | Es ist nämlich nach korrekter Anwendung der Identäten und des Distributivgesetzes:
Quelltext 1: 2:
| (a*b + c) mod n = ((((a mod n)*(b mod n) mod n) mod n) + (c mod n)) mod n = (a mod n) * (b mod n) mod n + (c mod n) | |
Ist es auch nicht.
Für a=12, b=44, c=21, n=54 wird
Quelltext 1: 2:
| (a*b + c) mod n = 9 (a mod n) * (b mod n) mod n + (c mod n) = 63 |
Richtig ist
Quelltext 1:
| (a*b + c) mod n = ((a mod n) * (b mod n) + (c mod n)) mod n |
was aber hier nicht viel bringt.
Beste Grüße
Mathematiker
_________________ Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
|
|
jfheins
      
Beiträge: 918
Erhaltene Danke: 158
Win 10
VS 2013, VS2015
|
Verfasst: Sa 07.09.13 16:43
Hi,
ja bei modularer Arithmetik muss man natürlich auch am Ende mod n rechnen. Habe oben einen entsprechenen Hinweis eingefügt.
Einen kleinen Einspuch bezüglich "was aber hier nicht viel bringt." möchte ich aber noch einbringen, weil die Formel ja durchaus das Problem löst. das Problem ist ja, von einer 24stelligen Zahl den modulao zu errechnen. Double genügt hierzu nicht.
Da oben schon IBAN angesprochen wurde, nehme ich mal die Zahl 141592653589793238462643 modulo 97:
Quelltext 1: 2: 3: 4: 5: 6: 7:
| 141592 653589 793238 462643 mod 97 = ( (141592 * 10^18) mod 97 + (653589 * 10^12) mod 97 + (793238 * 10^6) mod 97 + 462643 mod 97 ) mod 97 |
Jetzt die Zehnerpotenzen 'rausziehen und berechnen (kann man später hart kodieren) ergibt:
Quelltext 1: 2: 3: 4: 5: 6:
| ( (141592 mod 97)*89 + (653589 mod 97)*50 + (793238 mod 97)*27 + 462643 mod 97) ) mod 97 = (69*89 + 3*50 + 69*27 + 50) mod 97 = 56 |
Das gleiche Ergebnis liefert mir WolframAlpha.
Die Rechnungen sind alle innerhalb des Integer-Wertebereichs machbar, oder sind sogar <2^16.
Wenn ich das richtig sehe, benutzt du ja im Grunde die gleiche Eigenschaft, nur steht die Formel bei dir nicht direkt im Code.
|
|
Horst_H
      
Beiträge: 1654
Erhaltene Danke: 244
WIN10,PuppyLinux
FreePascal,Lazarus
|
Verfasst: Sa 07.09.13 21:05
Hallo,
@ jfheins:
Zitat: | Da oben schon IBAN angesprochen wurde, nehme ich mal die Zahl 141592653589793238462643 |
Das riecht nach pi ohne die führende 3
de.wikipedia.org/wik...100_Nachkommastellen
Gruß Horst
|
|
|