Code:
Der Umgang mit Kommazahlen Zahlen mit Komma sind deutlich kompliziertere Gebilde als solche ohne. das wird schon durch die Tatsache belegt, dass jede moderne Rechner-CPU über eine eingebaute Extra-Einheit verfügt, die ausschliesslich für die Verarbeitung von Kommazahlen dient. Aber auch als Programmierer muss man sich über die Kommazahlen etwas mehr Gedanken machen als über die Ganzzahlen.
Zunächst ist da einmal die Tatsache, dass man Kommazahlen auf unterschiedliche Weise ein- und ausgeben kann, und der VBA-Editor erweist sich als ziemlich hartnäckiger Klug******er: Er hat einfach seine eigene Vorstellung, wie die Eingabe auszusehen hat. Versuchen Sie einfach mal, das folgende Beispiel in der VBA-Umgebung abzutippen - oder kopieren Sie es einfach in ein Modul:
Public Sub Test()
Dim MySingle As Single
MySingle = 1.5e3
Debug.Print MySingle
MySingle = 1.5e5
Debug.Print MySingle
MySingle = 1.5e6
Debug.Print MySingle
MySingle = 1.5e7
Debug.Print MySingle
MySingle = 1.5E14
Debug.Print MySingle
MySingle = 1.5E15
Debug.Print MySingle
End Sub
VBA formatiert unsere Eingabe kurzerhand um. Die Ausgaben des Direktfensters sind im nächsten Code-Abschnitt als Kommentare eingefügt:
Public Sub Test()
Dim MySingle As Single
MySingle = 1500#
Debug.Print MySingle ' => 1500
MySingle = 150000#
Debug.Print MySingle ' => 150000
MySingle = 1500000#
Debug.Print MySingle ' => 1500000
MySingle = 15000000#
Debug.Print MySingle ' => 1,5E+7
MySingle = 150000000000000#
Debug.Print MySingle ' => 1,5E+14
MySingle = 1.5E+15
Debug.Print MySingle ' => 1,5E+15
End Sub
Es gelten also bei der Ein- und Ausgabe unterschiedliche Grenzen: Eingegebene Zahlen bis zum Exponenten 14 werden als Dezimalzahl dargestellt, was darüber hinausgeht, wird in die Exponentialschreibweise umformatiert. Bei der Ausgabe liegt die Grenze aber offensichtlich beim Exponenten 6.
Was dieses Beispiel auch zeigt: Kommazahlen müssen im VBA-Editor mit einem Punkt(!) als Dezimaltrennzeichen eingegeben werden. Natürlich ist man das als AutoCAD-Anwender eigentlich gewöhnt, aber es macht doch etwas stutzig, da VBA sonst konsequent auf die Verwendung des Kommas als Trennzeichen achtet.
Verhält es sich bei Kommazahlen genauso wie dei den Ganzzahlen, was das Überschreiten des Wertebereichs angeht? Das testen wir mit einem Beispiel:
Public Sub Test()
Debug.Print 1E+20! * 1E+20!
End Sub
Natürlich wird auch hier ein Überlauf angezeigt. 1E+20 * 1E+20 ergibt 1E+40, der Wertebereich eines Single hat seine Grenze aber bei 3,402823E+38.
Die schon hohen Grenzen des Single (und die noch wesentlich höheren des Double) sollten aber nicht zu der Annahme verleiten, dass die nun folgende, recht gewaltige Zahl so gespeichert werden kann, wie sie hier abgebildet ist:
12345678901234567890,123456789
Die Zahl ist zwar eindeutig kleiner als der Darstellungsbereich eines Single zulässt (etwa 1,2E+19, also noch lange nicht an der Grenze), trotzdem ist so so nicht zu verarbeiten. Schon bei der Eingabe im VBA-Editor wird sie beschnitten und sieht dann so aus (an den Punkt als Dezimaltrennzeichen bei der Eingabe denken!):
1.23456789012346E+19
Noch weiter beschnitten wird sie allerdings in der Ausgabe, und erst da zeigt sich, was wirklich gespeichert wird.
Public Sub Test()
Dim s As Single
s = 1.23456789012346E+19
Debug.Print s ' 1,234568E+19
End Sub
Der Datentyp Single arbeitet intern immer mit der Exponentialdarstellung. Die Mantisse einer Zahl hat bei einem Single immer 8 Stellen, das ist nicht VBA-spezifisch, sondern liegt in der Tatsache begründet, dass in 4 Bytes einfach keine größere Genauigkeit möglich ist.
Kommazahlen der Datentypen Single und Double sind also von der Tendenz her ungenau - damit muss man einfach leben. Wirklich genau sind nur 'glatte' Zahlen wie 1E+3 (1000). Spätestens dann, wenn irrationale Zahlen (z.B. π ins Spiel kommen, wird es aber ungenau. Mit dieser Ungenauigkeit kann man aber ganz gut leben, wenn man darüber Bescheid weiß.
Nun wird klarer, warum bei den Datentypen Single und Double von Realzahlen einfacher bzw. doppelter Genauigkeit die Rede ist. Der Double ist mit 8 Byte doppelt so groß wie der Single. Genau wie bei diesem ist ein Vierte des Speicherplatzes für den Exponenten und drei Viertel für die Mantisse. Das Komma wird explizit überhaupt nicht gespeichert, sondern liegt immer hinter der ersten Ziffer der Mantisse.
Wir verändern das letzte Beispiel noch einmal ganz minimal, um zu zeigen, dass das Zahlenliteral 1.23456789012346E+19 ein Double war, obwohl hier einem Single zugewiesen wurde:
Public Sub Test()
Dim s As Single
s = 12345678901234567890.123456789! ' Wird zu 1.234568E+19!
Debug.Print s
Debug.Print TypeName(s)
End Sub
Double-Zahlen können monströs groß sein, immerhin liegt die Grenze bei 1,79E+308. Eine sehr, sehr große Zahl, wenn man bedenkt, dass unser ganzer Globus aus lediglich ca. 1E+57 Atomen besteht. Wie ungenau jedoch auch Doubles sein können, lässt sich an unserer Beispielzahl nachvollziehen. Alle durchgestrichenen Ziffer lassen sich von Single bzw. Double nicht erfassen:
Single: 123456789|01234567890.123456789
Double: 1234567890123456|7890.123456789
Gespeichert werden also:
Single: 12345678000000000000.0
Double: 12345678901234560000.0