Entwickler-Ecke
Sonstiges (Delphi) - Modulo mit Double-Variable
mtm - Fr 06.09.13 17:07
Titel: Modulo mit Double-Variable
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 - 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 - Fr 06.09.13 17:41
Zu kurz gedacht :P
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 [
http://www.entwickler-ecke.de/viewtopic.php?p=679624#679624].
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.
Mathematiker - Fr 06.09.13 17:52
Hallo,
folgender Text testet die Korrektheit einer IBAN-Nummer:
Delphi-Quelltext
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
mandras - 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. - 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 [
https://en.wikipedia.org/wiki/Modulo_operation#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 - 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
jfheins - 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.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!