Zahlen
Ebenfalls von besonderer Bedeutung sind die verschiedenen Zahlentypen. Es gibt Zahlen mit Vorzeichen und ohne, Zahlen mit Kommawerten und ohne und diese jeweils in verschiedener Größe (mit entsprechendem Speicherbedarf).
Vorzeichenlose Zahlen sind vom Typ uint
(unsigned integer,
vorzeichenlose Ganzzahlen), vorzeichenbehaftete Zahlen sind vom Typ
int
(integer). Beide gibt es in den Größen 8, 16, 32 und 64
Bit Kapazität, die entsprechenden Datentypen heißen uint8
, uint16
,
uint32
und uint64
bzw. int8
, int16
, int32
und int64
.[1]
package main
import "fmt"
func main() {
var i uint64
// die Variable i darf nun z.B. keine
// negativen Werte speichern
i = 4
fmt.Println("i =", 2*i)
}
Die Größenangaben 8, 16, 32 und 64 beziehen sich auf die Anzahl der Bit, die
die Datentypen speichern können (und damit auf den Platzverbrauch). Ein
uint16
kann beispielsweise die Zahlen 0 bis 216-1 speichern, also 0 bis
65535. Die größte Zahl, die sich mit uint64
speichern lässt, ist etwas mehr
als 18 Trillionen. Die Zahlen, die auch negative Werte speichern können,
können nur etwa halb so große Werte speichern, beispielsweise bei int8
den
Zahlenbereich von -128 bis 127. Vorsicht ist gegeben, wenn sie über den Zahlenbereich hinausgehen:
package main
import "fmt"
func main() {
// int8 kann keine Werte größer als 127 speichern
var i int8
i = 127
i = i + 1
fmt.Println(i)
}
Die Ausgabe ist etwas überraschend -128. Das liegt an der Art und Weise, wie die Zahlen intern dargestellt werden (Zweierkomplement). Man muss also aufpassen, dass alle Berechnungen innerhalb des Wertebereichs liegen!
Der Datentyp byte
ist noch wichtig, da Datenquellen (Dateien auf der Festplatte oder Informationen, die über das Internet übertragen werden) immer als Reihe (slice) von byte
übergeben werden. Es ist ein Alias von uint8
, speichert also Werte von 0 bis 255.
Man kann Zeichenketten (string
) leicht in Bytes umwandeln (in der Kodierung UTF-8), alle anderen Datenstrukturen erfordern eine eigene Routine.
Gleitkommazahlen
Benötigt man Werte mit Nachkommastellen oder sehr große Werte, bieten sich sogenannte »Gleitkommazahlen« an. Sie heißen deswegen so, weil die Anzahl der Nachkommastellen, die gespeichert werden, abhängig vom Wert der Zahl ist.
Gleitkommazahlen gibt es in Go als float32
und float64
.
Interessant an den Datentypen ist, dass sie sehr kleine Werte (noch viel kleiner als z.B.
0,000000003) und sehr große Werte speichern können. Der kleinste positive Wert
bei float64
liegt bei etwa 5×10-324, der größte Wert bei ca. 1,8×10308.
Man muss ein wenig aufpassen, denn die Gleitkommazahlen speichern nicht immer
exakte Werte.
Vergleicht man Gleitkommazahlen miteinander, funktioniert das nicht immer:
if
-Fallunterscheidung wird im Kapitel Fallunterscheidungen behandelt.In diesem Fall sind a
und b
vom Typ float64
und ergeben in der Summe
nicht genau 0.3, sondern ein Wert, der minimal größer ist (versuche doch mal
herauszufinden, wie groß er ist). Die Lösung für den Fall oben wäre der
Vergleich, ob sich die Summe a+b
und der Wert 0.3
um nicht mehr als einen
sehr kleinen Wert (z.B. 0,000001) unterscheiden.
Gleitkommazahlen sollte man nicht verwenden, wenn man exakte Werte benötigt. Es ist verlockend, beispielsweise Geldbeträge (4,99 Euro) als Gleitkommazahl zu speichern. Damit handelt man sich schnell Fehler oder unvorhersehbare Situationen ein. Viele Fragen in den üblichen Internet-Foren (nicht nur in Bezug auf Go) kommen von mangelnder Genauigkeit der Gleitkommazahlen. Speichere solche Werte lieber als Ganzzahlen (z.B. 499) und füge das Komma bei der Ausgabe ggf. selber ein. |
Wenn man gewisse Ungenauigkeiten akzeptieren kann, eignen sich float32
und float64
wunderbar zum Rechnen.
int
und uint
ohne Größenangaben sind je nach Prozessortyp 32 oder 64 Bit groß, beide haben aber immer dieselbe Größe, d.h. wenn uint
64 Bit groß ist, ist auch int
64 Bit groß.