Big Numbers
Hallo,
heute möchte ich mal über richtig große Zahlen berichten, denn VBA hat genau mit denen Probleme diese zu verarbeiten.
Gerade in der Finanzwelt z.B. bei der Berechnung von Prüfziffern werden diese benötigt. Es sind dann schon spezielle Fälle, aber man sollte wissen wie man damit umgehen kann.
Schauen wir uns mal die Datentypen an, die uns in VBA zur Verfügung stehen:
– der Long-Datentyp ist bereits mit etwas über 2,1 Milliarden überfordert.
– Double schaft es immerhin auf 15 Stellen, bevor in die gerundete Exponential-Schreibweise gewechselt wird.
– eine weitere Möglichkeit ist der wenig bekannte Dezimal-Datentyp. Dieser lässt sich mit der Funktion CDec() herstellen, und damit haben wir schon 29 Stellen mit denen wir genau rechnen können.
Aber darüber hinaus? Nichts, Nada, Niente.
Angenommen Sie möchten von einer 36-Stelligen Zahl den Modulo nehmen, denn so groß kann maximal der BBAN (Basic Bank Account Number) nämlich werden: 30 Stellen Kontoidentifikation + 4 Stellen konvertiertes Länderkürzel + „00“
Mit dividieren so wie in den vorherigen Beitrag zum Modulo kommt man da nicht weit.
Aber es gibt für solche Fälle spezielle Rechenvorschriften, und eine möchte ich euch vorstellen, die Neun-Stellen-Regel.
Diese Regel besagt folgendes:
1. Von einer großen Zahl werden von links weg 9 Ziffern genommen werden, davon der Modulo genommen. 2. Es wird eine neue Zahl gebildet die mit dem berechneten Modulo beginnt, und mit Ziffern der großen Zahl bis auf 9 Stellen aufgefüllt wird. 3. Von dieser neuen Zahl wird wieder der Modulo genommen 4. Die Vorgänge 2. und 3. werden so lange wiederholt, bis alle Ziffern der ursprünglichen großen Zahl verarbeitet wurden. 5. Der Modulo, der bei der letzten Berechnung herauskommt, ist das Endergebnis.
Machen wir mal ein Beispiel.
Unsere große Zahl sei diese: 661400580’9000014’5786179’5321700’131400
Der Übersichtlichkeit ist diese in die verwendeten Blöcke eingeteilt.
Davon wollen wir den Modulo 97 bestimmen:
661400580 Mod 97 = 66 669000014 Mod 97 = 35 355786179 Mod 97 = 73 735321700 Mod 97 = 8 8131400 Mod 97 = 84
Der Modulo 97 userer großen Zahl ist also 84.
Um nun nicht ständig von Hand zu rechnen, erstellen wir aus diesen Informationen eine Prozedur.
Da wir von unserer großen Zahl (Dividend) nur Ziffern abschneiden, und nicht mit ihr rechnen, können wir diese als String-Parameter übergeben.
Public Function Modulo(ByVal Dividend As String, ByVal Devisor As Long) Dim NeueZahl As Long Dim ZwischenModulo As Variant Do While Len(Dividend) > 0 NeueZahl = CLng(ZwischenModulo & Left(Dividend, 9 - Len(CStr(ZwischenModulo)))) Dividend = Mid(Dividend, 10 - Len(CStr(ZwischenModulo))) ZwischenModulo = NeueZahl Mod Devisor Loop Modulo = ZwischenModulo End Function
Was euch sicherlich Kopfzerbrechen macht ist diese Zeile:
NeueZahl = CLng(ZwischenModulo & Left(Dividend, 9 – Len(CStr(ZwischenModulo))))
Im ersten Durchlauf der Schleife ist ZwischenModulo (Typ Variant) Leer bzw. Empty. Daher ist Len(CStr(Zwischenmodulo)) = 0. Es werden also genau 9 Stellen von der großen Zahl genommen.
Im zweiten und weiteren Durchläufen ist ZwischenModulo mit dem zuvor berechneten Modulo besetzt. Die NeueZahl bildet sich also aus ZwischenModulo & 9-Len(CStr(ZwischenModulo)) Stellen der großen Zahl, um wieder maximal 9 Stellen zu erhalten.
Die Zeile: Dividend = Mid(Dividend, 10 – Len(CStr(ZwischenModulo))) schneidet einfach nur die verwendeten Ziffern von der großen Zahl ab.
Da die Mid()-Funktion 1-Basiert ist, muss man Mid(Dividend,10) schreiben um 9 Stellen vom Dividend abzuschneiden, also alles richtig.
Vieleicht noch der Hinweis warum ZwischenModulo als Variant deklariert ist und nicht als Long: Wäre er als Long deklariert dann wäre im ersten Schleifendurchgang der Wert nicht Leer sondern 0, und die Länge von CStr(0) ist nunmal 1 und nicht 0.
OK, ich denke ich konnte euch die Problematiken von richtig großen Zahlen – den Big Numbers – ein wenig näher bringen. Und die neue Modulo-Funktion könnt ihr auch sofort in euren Projekten einsetzen und ihr läuft nicht Gefahr dass irgendwann der Wertebereich nicht ausreicht oder dass falsche Ergebnisse durch die gerundete Exponential-Darstellung von Double auftreten, denn diese können in der Finanzwelt schnell sehr teuer werden.
Bis dahin
© 2015 Andreas Vogt