Der Datentyp float in Go ermöglicht die Darstellung und Verarbeitung von Fließkommazahlen. Er eignet sich für mathematische Berechnungen, bei denen Dezimalstellen erforderlich sind, und unterstützt verschiedene Genauigkeitsstufen durch die Typen float32 und float64. Typische Anwendungsbereiche sind wissenschaftliche Berechnungen, Finanzanwendungen und überall dort, wo exakte Ganzzahlen nicht ausreichen.
Einführung
Float-Datentypen (Gleitkommazahlen) sind numerische Datentypen, die zur Darstellung von reellen Zahlen verwendet werden - also Zahlen, die Dezimalstellen haben können. Im Gegensatz zu Ganzzahlen (Integer) können Floats sowohl ganze Zahlen als auch Bruchzahlen darstellen. Der Begriff “Gleitkomma” kommt daher, dass das Komma (oder der Punkt) in der Zahl “gleiten” kann, um verschiedene Größenordnungen darzustellen.
Floats basieren auf dem IEEE 754-Standard, einem international anerkannten Standard für die Darstellung von Gleitkommazahlen in Computersystemen. Dieser Standard definiert, wie Gleitkommazahlen im Speicher gespeichert und verarbeitet werden.
Übersicht von Float-Typen
Go bietet verschiedene Float-Typen.
float32 (32-Bit Gleitkommazahl)
- Größe: 32 Bit (4 Bytes)
- Präzision: Etwa 7 Dezimalstellen
- Wertebereich: Ungefähr ±3.4×10^38
- Verwendung: Wenn Speicher kritisch ist und weniger Präzision ausreicht
float64 (64-Bit Gleitkommazahl)
- Größe: 64 Bit (8 Bytes)
- Präzision: Etwa 15-17 Dezimalstellen
- Wertebereich: Ungefähr ±1.7×10^308
- Verwendung: Standard für die meisten Anwendungen
Deklaration und Initialisierung
Grundlegende Deklaration
Bei der Deklaration ohne Initialisierung erhalten Float-Variablen automatisch den Nullwert 0.0.
package main
import "fmt"
func main() {
// Explizite Typ-Deklaration
var temperatur float64
var gewicht float32
fmt.Printf("temperatur: %v (Typ: %T)\n", temperatur, temperatur)
fmt.Printf("gewicht: %v (Typ: %T)\n", gewicht, gewicht)
}temperatur: 0 (Typ: float64)
gewicht: 0 (Typ: float32)Initialisierung mit Werten
Go inferiert bei Gleitkomma-Literalen standardmäßig float64, nicht float32.
package main
import "fmt"
func main() {
// Verschiedene Initialisierungsarten
var pi1 float64 = 3.14159
var pi2 = 3.14159
pi3 := 3.14159
var pi4 float32 = 3.14159
fmt.Printf("pi1: %v (Typ: %T)\n", pi1, pi1)
fmt.Printf("pi2: %v (Typ: %T)\n", pi2, pi2)
fmt.Printf("pi3: %v (Typ: %T)\n", pi3, pi3)
fmt.Printf("pi4: %v (Typ: %T)\n", pi4, pi4)
}pi1: 3.14159 (Typ: float64)
pi2: 3.14159 (Typ: float64)
pi3: 3.14159 (Typ: float64)
pi4: 3.14159 (Typ: float32)Float-Literale
Go unterstützt verschiedene Syntaxformen für Float-Literale.
package main
import "fmt"
func main() {
// Dezimalnotation
var a = 123.45
var b = .67 // Führende Null kann weggelassen werden
var c = 89. // Nachfolgende Ziffern können weggelassen werden
// Wissenschaftliche Notation
var d = 1.23e4 // 12300
var e = 1.23E-4 // 0.000123
var f = .123e2 // 12.3
// Hexadezimale Gleitkommazahlen
var g = 0x1.8p3 // 1.8₁₆ = 1.5₁₀, also 1.5 × 2³ = 12.0
var h = 0x.8p0 // 0.5
fmt.Printf("a: %v\n", a)
fmt.Printf("b: %v\n", b)
fmt.Printf("c: %v\n", c)
fmt.Printf("d: %v\n", d)
fmt.Printf("e: %v\n", e)
fmt.Printf("f: %v\n", f)
fmt.Printf("g: %v\n", g)
fmt.Printf("h: %v\n", h)
}a: 123.45
b: 0.67
c: 89
d: 12300
e: 0.000123
f: 12.3
g: 192
h: 0.5Operationen
Arithmetische Operationen
package main
import "fmt"
func main() {
var a float64 = 10.5
var b float64 = 3.2
// Grundrechenarten
summe := a + b
differenz := a - b
produkt := a * b
quotient := a / b
fmt.Printf("a + b = %.2f\n", summe)
fmt.Printf("a - b = %.2f\n", differenz)
fmt.Printf("a * b = %.2f\n", produkt)
fmt.Printf("a / b = %.2f\n", quotient)
}a + b = 13.70
a - b = 7.30
a * b = 33.60
a / b = 3.28Häufige Stolperfallen
Vergleich mit == ist gefährlich.
0.1 + 0.2 == 0.3 ist false. Float-Werte sind binäre Approximationen, kleine Rundungsfehler summieren sich. Vergleiche stattdessen über ein Epsilon: math.Abs(a-b) < 1e-9. Die passende Toleranz hängt von der Größenordnung der Werte ab — für sehr kleine oder sehr große Zahlen kann ein relatives Epsilon (math.Abs(a-b) < eps*math.Abs(b)) sinnvoller sein.
NaN ist mit nichts gleich — auch nicht mit sich selbst.
math.NaN() == math.NaN() liefert false, ebenso jeder andere Vergleich mit NaN. Das ist kein Bug, sondern IEEE 754. Zum Erkennen brauchst du math.IsNaN(x). Folge: if x != x { ... } ist ein gültiger NaN-Test, aber math.IsNaN ist lesbarer.
Konvertierung float → int trunkiert, sie rundet nicht.
int(3.9) ergibt 3, nicht 4. Wer kaufmännisch runden möchte, verwendet math.Round und konvertiert anschließend: int(math.Round(3.9)). Achtung bei negativen Werten: int(-3.9) ergibt -3 (Richtung Null), math.Floor(-3.9) dagegen -4.
math.Inf(1) und math.Inf(-1) sind echte Werte.
Eine Division wie 1.0 / 0.0 ist in Go zur Compile-Zeit ein Fehler, zur Laufzeit aber +Inf oder -Inf — kein Panic. 0.0 / 0.0 ergibt NaN. Prüfen mit math.IsInf(x, 1), math.IsInf(x, -1) oder math.IsInf(x, 0) für beide Vorzeichen.
float32 verliert Präzision gegenüber float64.
float32 hat etwa 7 signifikante Dezimalstellen, float64 rund 15-17. Wer float32 nur zur Speicherersparnis wählt, kassiert oft Rundungsfehler in Berechnungen. Faustregel: rechne in float64, speichere bei Bedarf in float32.
strconv.ParseFloat braucht den richtigen bitSize.
strconv.ParseFloat(s, 32) liefert technisch ein float64, dessen Wert aber so gerundet ist, als wäre er ein float32 — explizit konvertieren mit float32(f). Für float64 nimmt man bitSize=64. Bei Überlauf gibt ParseFloat ±Inf mit ErrRange zurück, nicht null.
Geld in float rechnen ist eine schlechte Idee.
0.10 + 0.20 ergibt 0.30000000000000004. In Finanz- und Buchhaltungs-Code arbeitet man mit ganzzahligen Cents (int64) oder einer Decimal-Bibliothek wie github.com/shopspring/decimal — nie mit float64.
Weiterführende Ressourcen
Externe Quellen
- Numeric types – Go Language Specification
- Paket
math– pkg.go.dev - Paket
strconv– pkg.go.dev - IEEE 754 – Wikipedia (Hintergrund)