Les nombres en Java
Travaillez avec les types numériques en Java — int, long, float, double — et comprenez la précision, le débordement et la classe Number.
Java distingue les nombres entiers et les nombres à virgule flottante, et dans chaque famille il existe plusieurs tailles. Choisir le bon type est important à la fois pour la justesse (précision, plage de valeurs) et la performance. Ce chapitre est un tour d'horizon ciblé des types numériques, de leurs littéraux, de leurs conversions et des pièges qui surprennent les débutants. Il suppose que vous savez déjà comment déclarer une variable et que vous avez vu l'ensemble complet des types de données primitifs.
Les primitives numériques
| Type | Bits | Plage | Style de littéral par défaut |
|---|---|---|---|
byte | 8 | -128 à 127 | byte b = 10; |
short | 16 | -32 768 à 32 767 | short s = 30_000; |
int | 32 | -2³¹ à 2³¹-1 (≈ ±2,1 milliards) | int i = 1_000_000; |
long | 64 | -2⁶³ à 2⁶³-1 | long l = 9_000L; |
float | 32 | IEEE 754 simple précision (~7 chiffres) | float f = 3.14f; |
double | 64 | IEEE 754 double précision (~16 chiffres) | double d = 3.14; |
Dans la pratique Java courante :
- Utilisez
intpour les compteurs, les index et la plupart des valeurs entières. - Utilisez
longquand vous risquez de dépasser ~2 milliards (tailles de fichiers, millisecondes depuis l'époque, générateurs d'ID). - Utilisez
doublepour les calculs en virgule flottante. - Utilisez
floatuniquement lorsque la mémoire est limitée ou qu'une API l'exige.
Littéraux entiers
Les chiffres ordinaires sont de type int :
int answer = 42;
int million = 1_000_000; // underscores are ignoredLe suffixe L (majuscule recommandée) pour long :
long big = 9_000_000_000L;Le préfixe 0x pour l'hexadécimal, 0b pour le binaire, 0 pour l'octal :
int hex = 0xFF; // 255
int bin = 0b1010; // 10
int oct = 0755; // 493 — be careful, easy to write by accident(Les littéraux octaux sont une source fréquente de bogues — 0123 n'est pas 123, c'est 83. Évitez les zéros initiaux sauf si vous voulez vraiment de l'octal.)
Littéraux à virgule flottante
Les décimales ordinaires sont de type double :
double pi = 3.14159;
double e = 2.71828;Le suffixe f pour float, d pour un double explicite (optionnel) :
float pif = 3.14f;
double pid = 3.14d;La notation scientifique fonctionne aussi :
double avogadro = 6.022e23;
double tiny = 1.0e-9;Conversion entre types numériques
Java effectue automatiquement une conversion élargie lorsqu'un type plus petit est affecté à un type plus grand (aucune donnée ne peut être perdue) :
int x = 7;
double promoted = x; // 7.0 — int widens to double automaticallyDans le sens inverse, il s'agit d'un rétrécissement : la valeur peut ne pas tenir, donc Java vous oblige à écrire un cast explicite et supprime silencieusement ce qui ne rentre pas. Il s'agit d'une troncature, pas d'un arrondi :
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 garbageEn raison de cela, ne rétrécissez que lorsque vous êtes certain que la valeur tient. Pour arrondir un double à l'entier le plus proche au lieu de tronquer, utilisez Math.round (voir Java Math).
Des conversions ont également lieu à l'intérieur des expressions. La division entière supprime le reste, ce qui surprend les débutants :
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 expressionPour les règles complètes sur les casts explicites, consultez Java Type Casting.
Débordement
L'arithmétique entière se reboucle silencieusement autour des limites du type. Aucune exception n'est levée :
int max = Integer.MAX_VALUE;
System.out.println(max + 1); // -2147483648 (Integer.MIN_VALUE)Pour une arithmétique avec vérification du débordement, utilisez la famille Math.exact :
Math.addExact(Integer.MAX_VALUE, 1); // throws ArithmeticException
Math.multiplyExact(100_000, 100_000); // throws tooUtile lorsque la justesse prime sur la performance — calculs financiers, tailles d'allocation, etc.
Précision des nombres à virgule flottante
double et float sont au format IEEE 754 binaire — ils ne peuvent pas représenter la plupart des fractions décimales exactement :
System.out.println(0.1 + 0.2); // 0.30000000000000004Ne comparez jamais des valeurs en virgule flottante avec ==. Comparez avec une tolérance :
double diff = Math.abs(a - b);
if (diff < 1e-9) { /* close enough */ }Pour les montants d'argent ou partout où vous avez besoin d'une arithmétique décimale exacte, utilisez BigDecimal :
import java.math.BigDecimal;
BigDecimal sum = new BigDecimal("0.1").add(new BigDecimal("0.2"));
System.out.println(sum); // 0.3Passez toujours des chaînes à new BigDecimal(...). Le constructeur double réintroduirait l'imprécision binaire.
Valeurs spéciales en virgule flottante
double possède trois valeurs qui ne sont pas des nombres ordinaires :
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)); // trueUtilisez Double.isNaN(x) pour tester NaN ; == ne fonctionnera pas.
Les classes enveloppantes
Chaque primitive a une classe enveloppante correspondante : Byte, Short, Integer, Long, Float, Double. Ces classes étendent la classe abstraite Number. Vous en avez besoin lorsque :
- Vous utilisez des collections qui contiennent des objets :
List<Integer>,Map<String, Double>. - Vous analysez des chaînes :
Integer.parseInt("42"),Double.parseDouble("3.14"). - Vous convertissez vers un autre type numérique via
.intValue(),.doubleValue(), etc.
Java effectue automatiquement l'autoboxing entre primitives et classes enveloppantes :
List<Integer> ids = new ArrayList<>();
ids.add(42); // autobox: int → Integer
int first = ids.get(0); // unbox: Integer → intBigInteger et BigDecimal
Lorsque les nombres peuvent être plus grands que long ou que vous avez besoin d'une précision décimale :
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"));Ils sont plus lents que les primitives, mais pour les cas qui en ont besoin, c'est le bon compromis.
Une démonstration
Et ensuite
- Java Math —
Math.abs,Math.round,Math.pow, et le reste de la boîte à outils numérique. - Java Operators — comment les opérateurs arithmétiques, de comparaison et bit à bit se comportent sur ces types.
- Java Booleans — le type à deux valeurs de Java, avec beaucoup moins de détails.