Java permet de manipuler des nombres de taille arbitraire pour utiliser de l'.
Ces nombres permettent d'aller au-delà des limites des types numériques primitifs, sans perte de précision, ou avec perte contrôlée.
Ils sont utilisés dans des domaines où le calcul avec tous les chiffres est nécessaire (la finance, calcul mathématique de précision, calcul de clés cryptographiques, ...).
Deux classes du paquetage codice_1 sont utilisées pour représenter deux types de nombres de taille arbitraire :
La précision est arbitraire mais reste soumise aux contraintes du système :
Nombre entier.
La classe codice_2 représente un nombre entier de taille arbitraire.
Un tel entier peut être créé à partir d'une chaîne de caractères, comme dans l'exemple suivant :
// À partir de la représentation en décimal :
BigInteger nombre_d_atomes = new BigInteger("7312154503213716790123144675124456301892787921502480260380150468277");
// À partir de la représentation en hexadécimal :
BigInteger cle = new BigInteger("A87B31697C6A9d9363B275E610F245C246A932B14569D273AE54CEC171CAFEFADE", 16);
Il peut aussi être créé à partir d'un tableau d'octets d'une représentation en complément à deux, dans l'ordre "big-endian" : l'octet le plus significatif est le premier.
// À partir d'un tableau d'octets de la représentation
// en complément à deux du nombre -17179869184 :
BigInteger nombre = new BigInteger(new byte[]{ 0xFC, 0x00, 0x00, 0x00, 0x00 });
Il peut aussi être créé à partir d'un nombre de type codice_5 en utilisant la méthode statique codice_6.
Comme les instances sont immuables, la méthode statique permet de retourner la même instance pour les valeurs fréquemment utilisées.
// À partir d'un nombre de type long :
BigInteger total_heures = BigInteger.valueOf(24L);
La classe définit aussi quelques instances comme membres statiques pour les valeurs classiques :
Opérations arithmétiques.
Les opérateurs en Java ne s'appliquent qu'aux types primitifs, excepté le plus codice_10 permettant de concaténer des chaînes de caractères.
Pour effectuer des opérations sur des instances de codice_2, il faut appeler les méthodes résumées dans le tableau ci-dessous.
Une instance de codice_2 étant immuable, les méthodes ne modifie pas l'objet lui-même mais retournent une nouvelle instance pour le résultat.
Si ce n'était pas le cas, il serait possible de modifier la valeur de codice_8 par exemple, ce qui fausserait les calculs utilisant la constante.
Comme les expressions complexes sur ces nombres entraînent la création de multiples instances, il n'est pas utile de garder les résultats intermédiaires, sauf de manière temporaire pour déboguer l'expression.
Il est donc courant d'enchaîner les méthodes :
BigInteger
 a = new BigInteger("1500000000"),
 b = new BigInteger("578000057"),
 c = new BigInteger("1234567");
// d = ( a+b ) * c / 10
BigInteger d = a.add(b).multiply(c).divide(BigInteger.TEN);
Autres opérations arithmétiques sur ces nombres :
Opérations sur les bits.
Les bits des entiers de taille arbitraire peuvent aussi être manipulés.
Autres opérations sur les bits de ces nombres :
Opérations arithmétiques modulaires.
La classe codice_2 a également des méthodes pour l'.
Le modulo "m" détermine l'intervalle des entiers utilisés : de 0 (inclus) à "m" (exclus).
Générer un nombre probablement premier.
Les algorithmes de cryptographie utilisent souvent des problèmes mathématiques difficiles à résoudre en un temps raisonnable, dont celui de la décomposition des grands nombres entiers en facteur premiers.
Paramètres :
Conversions.
La classe codice_2 est une sous-classe de codice_20, comme les classes englobant les nombres primitifs.
Elle possède donc les mêmes méthodes de conversions, qui tronque le résultat s'il ne loge pas dans le type demandé :
Pour les types entiers, il y a également une variante retournant une valeur exacte ou une exception de type codice_21 si le nombre ne loge pas dans le type demandé :
Nombre décimal.
La classe codice_3 représente un nombre décimal de taille arbitraire défini par un entier de taille arbitraire (type codice_2) et un nombre entier de type codice_24 définissant la position de la virgule.
Il y a donc une limite (celle du type codice_24 32 bits) sur l'échelle.
// À partir de la représentation en décimal :
BigDecimal pi = new BigDecimal("3.14159265358979323846264338327950288419716939937510582097494459230781640628");
Il est possible de créer une instance de codice_3 à partir d'une valeur de type codice_27.
Cependant, il peut y avoir une perte de précision :
BigDecimal un_dixieme = new BigDecimal(0.1D);
// 0.1000000000000000055511151231257827021181583404541015625
L'utilisation de la méthode statique codice_6 permet d'éviter cette perte de précision car la valeur est convertie en chaîne de caractère en appelant la méthode codice_29 :
BigDecimal un_dixieme = BigDecimal.valueOf(0.1D); // 0.1
// Équivalent :
BigDecimal un_dixieme = new BigDecimal(Double.toString(0.1D)); // 0.1
Cependant la précision possible du nombre construit par ce moyen est limitée par celle du type codice_27.
La classe définit aussi quelques instances comme membres statiques pour les valeurs classiques :
Précision et échelle.
La méthode codice_34 retourne la précision, c'est-à-dire le nombre de chiffres décimaux du nombre.
La méthode codice_35 retourne la position de la virgule par rapport au dernier chiffre de précision.
La méthode codice_36 retourne l'entier de type codice_2 représentant la valeur entière sans échelle ; son nombre de chiffres vaut codice_34.
Exemples :
La valeur représentée par un nombre de type codice_3 est donc formula_3.
Contexte.
La classe codice_40 est utilisée par plusieurs méthodes comme contexte pour spécifier la précision voulue et le mode d'arrondi à appliquer.
Arrondi.
La méthode codice_41 arrondit le nombre selon le mode et à la précision indiqués dans l'objet codice_40 donné en argument.
BigDecimal a = new BigDecimal("12345.6789")
 .round(new MathContext(2, RoundingMode.HALF_EVEN));
a.toPlainString() // 12000
a.scale() // -3
Tandis que la méthode codice_43 change l'échelle du nombre :
BigDecimal a = new BigDecimal("12345.6789")
 .setScale(2, RoundingMode.HALF_EVEN);
a.toPlainString() // 12345.68
a.scale() // 2
Opérations arithmétiques.
Les opérateurs en Java ne s'appliquent qu'aux types primitifs, excepté le plus codice_10 permettant de concaténer des chaînes de caractères.
Pour effectuer des opérations sur des instances de codice_3, il faut appeler les méthodes résumées dans le tableau ci-dessous.
Ces méthodes sont similaires à celles de la classe codice_2, avec une variante acceptant un objet codice_40 pour arrondir le résultat, et un comportement différent pour la division.
Une instance de codice_3 étant immuable, les méthodes ne modifie pas l'objet lui-même mais retournent une nouvelle instance pour le résultat.
Si ce n'était pas le cas, il serait possible de modifier la valeur de codice_32 par exemple, ce qui fausserait les calculs utilisant la constante.
Comme les expressions complexes sur ces nombres entraînent la création de multiples instances, il n'est pas utile de garder les résultats intermédiaires, sauf de manière temporaire pour déboguer l'expression.
Il est donc courant d'enchaîner les méthodes :
BigDecimal
 a = new BigDecimal("1500000000"),
 b = new BigDecimal("5780.00057"),
 c = new BigDecimal("12345.67");
// d = ( a+b ) * c / 10 Arrondi à 8 chiffres de précision
BigDecimal d = a.add(b).multiply(c).divide(BigDecimal.TEN, 8, BigDecimal.ROUND_HALF_EVEN);
Si la division génère un nombre infini de chiffres, il faut préciser l'arrondi voulu :
BigDecimal.ONE.divide(BigDecimal.valueOf(5L));
// --> 0.2
BigDecimal.ONE.divide(BigDecimal.valueOf(7L));
// --> java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
BigDecimal.ONE.divide(BigDecimal.valueOf(7L), 8, BigDecimal.ROUND_HALF_EVEN);
// --> 0.14285714
// Ou en utilisant un contexte d'arrondi réutilisable :
MathContext mc = new MathContext(8, RoundingMode.HALF_EVEN);
BigDecimal.ONE.divide(BigDecimal.valueOf(7L), mc);
// --> 0.14285714
Autres opérations arithmétiques sur ces nombres :
Comparaison.
Exemple :
BigDecimal a = new BigDecimal("1"); // entier = 1, scale = 0
BigDecimal b = new BigDecimal("1.0"); // entier = 10, scale = 1
a.equals(b) // false <!>
a.compareTo(b) == 0 // true
La méthode codice_50 est celle qu'il faut utiliser pour comparer les nombres de type codice_3.
Conversions.
La classe codice_3 est une sous-classe de codice_20, comme les classes englobant les nombres primitifs.
Elle possède donc les mêmes méthodes de conversions, qui tronquent le résultat s'il ne loge pas dans le type demandé :
Pour les types entiers, il y a également une variante retournant une valeur exacte ou une exception de type codice_21 si le nombre ne loge pas dans le type demandé :
Performances.
Comme expliqué en introduction, la précision est arbitraire mais reste soumise aux contraintes du système et a un impact sur les performances de l'application.
Plus la précision est grande, plus la quantité de mémoire utilisée est importante.
Cela impacte aussi la vitesse d'exécution des opérations car elle est dépendante de la précision employée (temps proportionnel/quadratique/exponentiel).
Dans les expressions longues, certaines opérations peuvent augmenter la précision des résultats.
Il peut être important de réduire la précision des résultats intermédiaires avant de poursuivre les opérations, afin de réduire la mémoire utilisée et permettre un temps d'exécution moindre.