W3docs

Java Zahlen

Arbeite mit numerischen Typen in Java — int, long, float, double — und verstehe Präzision, Überlauf und die Number-Klasse.

Java unterscheidet zwischen ganzzahligen und Gleitkommazahlen, und innerhalb jeder Familie gibt es mehrere Größen. Die Wahl des richtigen Typs ist sowohl für Korrektheit (Präzision, Wertebereich) als auch für die Leistung wichtig. Dieses Kapitel ist ein gezielter Durchgang durch die numerischen Typen, ihre Literale, Konvertierungen und die Fallstricke, die Anfänger überraschen. Es setzt voraus, dass du bereits weißt, wie man eine Variable deklariert, und die vollständige Liste der primitiven Datentypen gesehen hast.

Die numerischen Primitiven

TypBitsWertebereichStandard-Literalform
byte8-128 bis 127byte b = 10;
short16-32.768 bis 32.767short s = 30_000;
int32-2³¹ bis 2³¹-1 (≈ ±2,1 Milliarden)int i = 1_000_000;
long64-2⁶³ bis 2⁶³-1long l = 9_000L;
float32IEEE 754 einfache Genauigkeit (~7 Stellen)float f = 3.14f;
double64IEEE 754 doppelte Genauigkeit (~16 Stellen)double d = 3.14;

Im alltäglichen Java:

  • Verwende int für Zähler, Indizes und die meisten ganzzahligen Werte.
  • Verwende long, wenn der Wert ~2 Milliarden überschreiten könnte (Dateigrößen, Millisekunden seit der Epoche, ID-Generatoren).
  • Verwende double für Gleitkomma-Arithmetik.
  • Verwende float nur, wenn der Speicher knapp ist oder eine API es erfordert.

Ganzzahl-Literale

Einfache Ziffern sind int:

int answer = 42;
int million = 1_000_000;     // underscores are ignored

Suffix L (Großbuchstabe bevorzugt) für long:

long big = 9_000_000_000L;

Präfix 0x für Hexadezimal, 0b für Binär, 0 für Oktal:

int hex = 0xFF;        // 255
int bin = 0b1010;      // 10
int oct = 0755;        // 493 — be careful, easy to write by accident

(Oktal-Literale sind eine häufige Fehlerquelle — 0123 ist nicht 123, sondern 83. Vermeide führende Nullen, es sei denn, du meinst wirklich Oktal.)

Gleitkomma-Literale

Einfache Dezimalzahlen sind double:

double pi = 3.14159;
double e = 2.71828;

Suffix f für float, d für explizites double (optional):

float pif = 3.14f;
double pid = 3.14d;

Wissenschaftliche Notation funktioniert ebenfalls:

double avogadro = 6.022e23;
double tiny = 1.0e-9;

Konvertierung zwischen numerischen Typen

Java führt automatisch eine Erweiterungskonvertierung durch, wenn ein kleinerer Typ in einen größeren fließt (kein Datenverlust möglich):

int x = 7;
double promoted = x;   // 7.0 — int widens to double automatically

In die andere Richtung ist es eine einengende Konvertierung: Der Wert passt möglicherweise nicht, daher erzwingt Java einen expliziten Cast und verwirft stillschweigend, was nicht passt. Es wird abgeschnitten, nicht gerundet:

double d = 9.99;
int i = (int) d;       // 9 — the fraction is dropped, never rounded

long big = 9_000_000_000L;
int truncated = (int) big;   // 410065408 — high bits lost, value is garbage

Daher solltest du nur dann einengen, wenn du sicher bist, dass der Wert passt. Um ein double auf die nächste ganze Zahl zu runden statt abzuschneiden, verwende Math.round (siehe Java Math).

Konvertierungen finden auch innerhalb von Ausdrücken statt. Die ganzzahlige Division verwirft den Rest, was Anfänger überrascht:

System.out.println(7 / 2);     // 3   — both operands are int, so int division
System.out.println(7 / 2.0);   // 3.5 — one double operand promotes the whole expression

Die vollständigen Regeln für explizite Casts findest du unter Java Type Casting.

Überlauf

Ganzzahl-Arithmetik läuft still um die Grenzen des Typs herum. Es wird keine Ausnahme ausgelöst:

int max = Integer.MAX_VALUE;
System.out.println(max + 1);   // -2147483648 (Integer.MIN_VALUE)

Für überlaufgeprüfte Arithmetik verwende die Math.exact-Familie:

Math.addExact(Integer.MAX_VALUE, 1);   // throws ArithmeticException
Math.multiplyExact(100_000, 100_000);  // throws too

Nützlich, wenn Korrektheit wichtiger ist als Leistung — Finanzberechnungen, Allokationsgrößen usw.

Gleitkomma-Präzision

double und float sind IEEE 754 binär — sie können die meisten Dezimalbrüche nicht exakt darstellen:

System.out.println(0.1 + 0.2);   // 0.30000000000000004

Vergleiche Gleitkommazahlen niemals mit ==. Vergleiche innerhalb einer Toleranz:

double diff = Math.abs(a - b);
if (diff < 1e-9) { /* close enough */ }

Für Geldbeträge oder überall dort, wo du exakte Dezimalarithmetik benötigst, verwende BigDecimal:

import java.math.BigDecimal;

BigDecimal sum = new BigDecimal("0.1").add(new BigDecimal("0.2"));
System.out.println(sum);   // 0.3

Übergebe immer Strings an new BigDecimal(...). Der double-Konstruktor würde die binäre Ungenauigkeit wieder einführen.

Besondere Gleitkomma-Werte

double hat drei Werte, die keine gewöhnlichen Zahlen sind:

double posInf = Double.POSITIVE_INFINITY;
double negInf = Double.NEGATIVE_INFINITY;
double nan = Double.NaN;

System.out.println(1.0 / 0);          // Infinity
System.out.println(-1.0 / 0);         // -Infinity
System.out.println(0.0 / 0);          // NaN

System.out.println(nan == nan);       // false — NaN compares unequal to everything
System.out.println(Double.isNaN(nan)); // true

Verwende Double.isNaN(x), um auf NaN zu prüfen; == funktioniert nicht.

Die Wrapper-Klassen

Jeder Primitiv hat eine entsprechende Wrapper-Klasse: Byte, Short, Integer, Long, Float, Double. Die Wrapper erweitern die abstrakte Klasse Number. Du benötigst sie, wenn:

  • Du Collections verwendest, die Objekte enthalten: List<Integer>, Map<String, Double>.
  • Du aus Strings parsierst: Integer.parseInt("42"), Double.parseDouble("3.14").
  • Du über .intValue(), .doubleValue() usw. in einen anderen numerischen Typ konvertierst.

Java führt automatisch Autoboxing zwischen Primitiv und Wrapper durch:

List<Integer> ids = new ArrayList<>();
ids.add(42);            // autobox: int → Integer
int first = ids.get(0); // unbox: Integer → int

BigInteger und BigDecimal

Wenn Zahlen größer als long sein können oder du Dezimalpräzision benötigst:

import java.math.BigInteger;

BigInteger huge = new BigInteger("123456789012345678901234567890");
huge.multiply(huge);

BigDecimal price = new BigDecimal("19.95");
BigDecimal tax = price.multiply(new BigDecimal("0.07"));

Sie sind langsamer als Primitive, aber für die Fälle, in denen sie benötigt werden, ist das der richtige Kompromiss.

Eine Demonstration

java— editable, runs on the server

Was kommt als Nächstes

  • Java MathMath.abs, Math.round, Math.pow und der Rest des numerischen Werkzeugkastens.
  • Java Operators — wie sich Arithmetik-, Vergleichs- und bitweise Operatoren auf diese Typen verhalten.
  • Java Booleans — Javas zweiweriger Typ, mit viel weniger Details.

Übungen

Übung
Welcher Typ ist für einen Geldbetrag in Java am besten geeignet?
Welcher Typ ist für einen Geldbetrag in Java am besten geeignet?
Was this page helpful?