JavaRush /Blog Java /Random-FR /BigDecimal en Java

BigDecimal en Java

Publié dans le groupe Random-FR
Bonjour! Dans la conférence d'aujourd'hui, nous parlerons de grands nombres. Non, à propos des VRAIMENT GRANDS. Auparavant , nous avons vu plus d'une fois un tableau de plages de valeurs pour les types de données primitifs. Cela ressemble à ceci :
Type primitif Taille en mémoire Plage de valeurs
octet 8 bits -128 à 127
court 16 bits à -32768 à 32767
carboniser 16 bits de 0 à 65536
int 32 bits du -2147483648 au 2147483647
long 64 bits de -9223372036854775808 à 9223372036854775807
flotter 32 bits de (2 à la puissance -149) à ((2-2 à la puissance -23)*2 à la puissance 127)
double 64 bits de (-2 à la puissance 63) à ((2 à la puissance 63) - 1)
booléen 8 (lorsqu'il est utilisé dans des tableaux), 32 (lorsqu'il est utilisé dans des non-tableaux) vrai ou faux
Si nous parlons d'entiers, le type de données le plus volumineux est long , et lorsque nous parlons de nombres à virgule flottante, double . Mais que se passe-t-il si le nombre dont nous avons besoin est si grand qu’il ne rentre même pas dans une longue période ? La plage des valeurs Long possibles est assez large, mais toujours limitée à une certaine taille - 64 bits. Que pouvons-nous imaginer si notre très grand nombre pèse 100 bits ? Heureusement, vous n’avez rien à inventer. En Java, deux classes spéciales ont été créées pour de tels cas : BigInteger (pour les entiers) et BigDecimal (pour les nombres à virgule flottante). Quelle est leur particularité ? Tout d’abord, ils n’ont théoriquement pas de taille maximale. Théoriquement, car il n’existe pas d’ordinateurs dotés d’une mémoire infinie. Et si vous créez dans le programme un nombre supérieur à la taille de la mémoire de l'ordinateur, bien sûr, le programme ne fonctionnera pas. Mais de tels cas sont peu probables. On peut donc dire que la taille des nombres BigIntegerest BigDecimalpratiquement illimitée. A quoi servent ces cours ? Tout d’abord, pour les calculs exigeant une précision extrêmement élevée. Il existe par exemple des programmes dans lesquels la vie humaine peut dépendre de la précision des calculs (logiciels pour avions et fusées ou pour équipements médicaux). Par conséquent, même si la 150e décimale joue un rôle important, BigDecimalc’est le meilleur choix. De plus, ces objets sont souvent utilisés dans le monde de la finance, où la précision des calculs jusqu'aux plus petites valeurs est également extrêmement importante. Comment travailler avec des objets BigIntegeret BigDecimalqu'est-ce qu'il est important de retenir à leur sujet ? Les objets de ces classes sont créés comme ceci :
public class Main {

   public static void main(String[] args) {

       BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
       System.out.println(integer);

       BigDecimal decimal = new BigDecimal("123.444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444");
       System.out.println(decimal);
   }
}
Passer une chaîne en paramètre n'est qu'un des constructeurs possibles. Ici, nous utilisons des chaînes parce que nos nombres dépassent les valeurs maximales longet double, et d'une manière ou d'une autre, nous devons expliquer au compilateur exactement quel nombre nous voulons obtenir :) Il suffit de passer le nombre 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 ne sera pas travail : Java essaiera de "s'adapter" le numéro transmis dans l’un des types de données primitifs, mais il ne rentrera dans aucun d’entre eux. Par conséquent, utiliser une chaîne pour transmettre le nombre souhaité est une bonne option. Les deux classes peuvent extraire automatiquement les valeurs numériques des chaînes transmises. Un autre point important à retenir lorsque vous travaillez avec un grand nombre de classes est que leurs objets sont immuables ( Immutable) . Vous connaissez déjà bien le principe d'immuabilité à travers l'exemple d'une classe Stringet de classes wrapper pour primitives (Integer, Long et autres).
import java.math.BigInteger;

public class Main {

   public static void main(String[] args) {

       BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
       System.out.println(integer);

       integer.add(BigInteger.valueOf(33333333));
       System.out.println(integer);

   }
}
Sortie de la console :

1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
Nos chiffres n’ont pas changé, comme on peut s’y attendre. Pour que l'opération d'ajout réussisse, vous devez créer un nouvel objet et lui affecter le résultat de l'ajout.
import java.math.BigInteger;

public class Main {

   public static void main(String[] args) {

       BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
       System.out.println(integer);

       BigInteger result = integer.add(BigInteger.valueOf(33333333));
       System.out.println(result);

   }
}
Sortie de la console :

1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111144444444
Maintenant, tout fonctionne comme il se doit :) Au fait, avez-vous remarqué à quel point l'opération d'addition semble inhabituelle ?
BigInteger result = integer.add(BigInteger.valueOf(33333333));
C'est un autre point important. Les classes à grand nombre n'utilisent pas les opérateurs +-*/ dans leur fonctionnement, mais fournissent à la place un ensemble de méthodes. Jetons un coup d'œil aux principales (vous pouvez, comme toujours, retrouver la liste complète des méthodes dans la documentation Oracle : ici et ici ).
  1. méthodes pour effectuer des opérations arithmétiques : add() , subtract(), multiply(), divide(). Utilisé respectivement pour les opérations d'addition, de soustraction, de multiplication et de division.

  2. doubleValue(), intValue(), floatValue(), longValue()etc. - Utilisé pour convertir un grand nombre en un type primitif Java. Soyez prudent lorsque vous les utilisez et rappelez-vous la différence de capacité !

    import java.math.BigInteger;
    
    public class Main {
    
       public static void main(String[] args) {
    
           BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
    
           long result = integer.longValue();
           System.out.println(result);
    
       }
    }

    Sortie de la console :

    
    8198552921648689607
  3. min()et max()- permettent de trouver la valeur minimale et maximale de deux grands nombres transmis.
    Attention : les méthodes ne sont pas statiques !

    import java.math.BigInteger;
    
    public class Main {
    
       public static void main(String[] args) {
    
           BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
           BigInteger integer2 = new BigInteger("222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222");
    
           System.out.println(integer.max(integer2));
    
       }
    }

    Sortie de la console :

    
    222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222

Contrôle d'arrondi BigDecimal

Ce sujet est inclus dans une section distincte, car arrondir de grands nombres et les ajuster n'est pas une chose si simple. Vous pouvez définir le nombre de décimales pour un nombre BigDecimalà l'aide du setScale(). Par exemple, nous souhaitons définir la précision du nombre 111,5555555555 à trois décimales. Cependant, nous ne pourrons pas passer le chiffre 3 en argument à la méthode setScale()et ainsi résoudre notre problème. Comme mentionné ci-dessus, BigDecimalce sont des chiffres destinés à des calculs avec une précision accrue. Dans sa forme actuelle, notre nombre comporte 10 décimales. Nous voulons en supprimer 7 et n'en laisser que 3. Par conséquent, en plus du nombre 3, nous devons passer le mode d'arrondi en paramètre . Il existe 8 modes d'arrondi au total BigDecimal. Beaucoup! Mais si vous avez besoin d'affiner la précision des calculs dans le programme, vous aurez tout ce dont vous avez besoin pour cela. Voici donc les 8 modes d'arrondi disponibles dans BigDecimal:
  1. ROUND_CEILING- arrondir

    111.5555555555 -> setScale(3, ROUND_CEILING) -> 111.556
  2. ROUND_DOWN- rejet de décharge

    111.5555555555 -> setScale(3, ROUND_DOWN) -> 111.555
  3. ROUND_FLOOR- arrondir à l'inférieur

    111.5555555555 -> setScale(3, ROUND_FLOOR) -> 111.555

  4. ROUND_HALF_UP— arrondir si le nombre après la virgule >= 0,5

    0.55 -> setScale(1, ROUND_HALF_UP) -> 0.6
    0.54 -> setScale(1, ROUND_HALF_UP) -> 0.5
  5. ROUND_HALF_DOWN— arrondir si le nombre après la virgule > 0,5

    0.55 -> setScale(1, ROUND_HALF_DOWN) -> 0.5
    0.56 -> setScale(1, ROUND_HALF_DOWN) -> 0.6
  6. ROUND_HALF_EVEN— l'arrondi dépendra du nombre à gauche de la virgule décimale. Si le nombre à gauche est pair, alors l’arrondi sera effectué vers le bas. Si le nombre à gauche de la virgule décimale est impair, il sera arrondi à l’unité supérieure.

    2.5 -> setScale(0, ROUND_HALF_EVEN) -> 2

    Le nombre à gauche de la virgule décimale – 2 – est pair. L'arrondi se produit vers le bas. Puisque nous avons besoin de 0 décimale, le résultat sera 2.

    3.5 -> setScale(0, ROUND_HALF_EVEN) -> 4

    Le nombre à gauche de la virgule décimale – 3 – est impair. L'arrondi se produit vers le haut. Puisque nous avons besoin de 0 décimale, le résultat sera 4.

  7. ROUND_UNNECCESSARY— utilisé dans les cas où le mode d'arrondi doit être transmis à une méthode, mais où le nombre n'a pas besoin d'être arrondi. Si vous essayez d'arrondir un nombre lorsque le mode ROUND_UNNECCESSARY est défini, une ArithmeticException est levée.

    3.51 -> setScale(1, ROUND_UNNECCESSARY) -> ArithmeticException
  8. ROUND_UP- arrondir.

    111.5551 -> setScale(3, ROUND_UP) -> 111.556

Comparaison de grands nombres

Cette question est également importante. Vous vous souvenez déjà que la méthode est utilisée pour comparer des objets en Java equals(). Il est soit fourni par le langage lui-même (dans le cas des classes intégrées de Java), soit remplacé par le programmeur. Mais dans le cas d'objets de classe, il n'est pas recommandé BigDecimald'utiliser la méthode equals()de comparaison. La raison en est que la BigDecimal.equals()méthode à deux nombres renvoie vrai uniquement si les deux nombres ont la même valeur et la même échelle : Comparons le comportement des méthodes equals()y Doubleet y BigDecimal:
import java.math.BigDecimal;

public class Main {

   public static void main(String[] args) {

       Double a = 1.5;
       Double b = 1.50;

       System.out.println(a.equals(b));

       BigDecimal x = new BigDecimal("1.5");
       BigDecimal y = new BigDecimal("1.50");

       System.out.println(x.equals(y));

   }
}
Sortie de la console :

true
false
Comme vous pouvez le constater, les nombres 1,5 et 1,50 dans le cas de c BigDecimalse sont avérés inégaux ! Cela s'est produit précisément à cause des spécificités de la méthode utilisée equals()en classe BigDecimal. Pour une comparaison plus correcte des deux, BigDecimalil est préférable d'utiliser la méthode compareTo():
import java.math.BigDecimal;

public class Main {

   public static void main(String[] args) {

       BigDecimal x = new BigDecimal("1.5");
       BigDecimal y = new BigDecimal("1.50");

       System.out.println(x.compareTo(y));

   }
}
Sortie de la console :

0
La méthode compareTo()a renvoyé 0, ce qui signifie égal à 1,5 et 1,50. C'est le résultat sur lequel nous comptions ! :) Ceci conclut notre leçon d'aujourd'hui. Il est temps de se remettre aux tâches ! :)
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION