JavaRush /Blog Java /Random-ES /GranDecimal en Java

GranDecimal en Java

Publicado en el grupo Random-ES
¡Hola! En la conferencia de hoy hablaremos de grandes números. No, sobre los REALMENTE GRANDES. Anteriormente , hemos visto una tabla de rangos de valores para tipos de datos primitivos más de una vez. Se parece a esto:
tipo primitivo Tamaño en memoria Rango de valores
byte 8 bits -128 a 127
corto 16 bits a -32768 a 32767
carbonizarse 16 bits de 0 a 65536
En t 32 bits de -2147483648 a 2147483647
largo 64 bits de -9223372036854775808 a 9223372036854775807
flotar 32 bits de (2 elevado a -149) a ((2-2 elevado a -23)*2 elevado a 127)
doble 64 bits de (-2 elevado a 63) a ((2 elevado a 63) - 1)
booleano 8 (cuando se usa en matrices), 32 (cuando se usa en no matrices) verdadero o falso
Si hablamos de números enteros, el tipo de datos con mayor capacidad es long , y cuando hablamos de números de coma flotante, double . Pero ¿qué pasa si el número que necesitamos es tan grande que ni siquiera cabe en un espacio largo ? El rango de posibles valores Long es bastante grande, pero aún está limitado a un cierto tamaño: 64 bits. ¿Qué se nos ocurre si nuestro Número Muy Grande pesa 100 bits? Afortunadamente, no es necesario inventar nada. En Java, se crearon dos clases especiales para tales casos: BigInteger (para números enteros) y BigDecimal (para números de punto flotante). ¿Cuál es su característica? En primer lugar, teóricamente no tienen un tamaño máximo. En teoría, porque no existen ordenadores con memoria infinita. Y si crea un número en el programa que es mayor que el tamaño de la memoria de la computadora, por supuesto, el programa no funcionará. Pero estos casos son poco probables. Por tanto, podemos decir que el tamaño de los números BigIntegeres BigDecimalprácticamente ilimitado. ¿Para qué sirven estas clases? En primer lugar, para cálculos con requisitos de precisión extremadamente altos. Existen, por ejemplo, programas en los que la vida humana puede depender de la precisión de los cálculos (software para aviones y cohetes o para equipos médicos). Por lo tanto, si incluso el decimal 150 juega un papel importante, BigDecimales la mejor opción. Además, con bastante frecuencia estos objetos se utilizan en el mundo de las finanzas, donde la precisión de los cálculos hasta los valores más pequeños también es extremadamente importante. ¿Cómo trabajar con objetos BigIntegery BigDecimalqué es importante recordar sobre ellos? Los objetos de estas clases se crean así:
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);
   }
}
Pasar una cadena como parámetro es sólo uno de los posibles constructores. Aquí usamos cadenas porque nuestros números exceden los valores máximos longy double, y de alguna manera necesitamos explicarle al compilador exactamente qué número queremos obtener :) Simplemente pase el número 111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 No funciona : Java intentará “adaptarse” el número pasado en uno de los tipos de datos primitivos, pero no cabe en ninguno de ellos. Por tanto, utilizar una cadena para pasar el número deseado es una buena opción. Ambas clases pueden extraer automáticamente valores numéricos de cadenas pasadas. Otro punto importante a recordar cuando se trabaja con clases de números grandes es que sus objetos son inmutables ( Immutable) . Ya está familiarizado con el principio de inmutabilidad a través del ejemplo de una clase Stringy clases contenedoras para primitivas (Integer, Long y otras).
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);

   }
}
Salida de consola:

1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
Nuestros números no han cambiado, como era de esperar. Para que la operación de suma se realice correctamente, debe crear un nuevo objeto y asignarle el resultado de la suma.
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);

   }
}
Salida de consola:

1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111144444444
Ahora todo funciona como debería :) Por cierto, ¿notaste lo inusual que parece la operación de suma?
BigInteger result = integer.add(BigInteger.valueOf(33333333));
Este es otro punto importante. Las clases con números grandes no utilizan los operadores +-*/ en su operación, sino que proporcionan un conjunto de métodos. Echemos un vistazo a los principales (puede, como siempre, encontrar una lista completa de métodos en la documentación de Oracle: aquí y aquí ).
  1. métodos para realizar operaciones aritméticas: add() , subtract(), multiply(), divide(). Se utiliza para operaciones de suma, resta, multiplicación y división respectivamente.

  2. doubleValue(), intValue(), floatValue(), longValue()etc. - Se utiliza para convertir un número grande a un tipo primitivo de Java. ¡Ten cuidado al usarlos y recuerda la diferencia de capacidad!

    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);
    
       }
    }

    Salida de consola:

    
    8198552921648689607
  3. min()y max()- le permitirá encontrar el valor mínimo y máximo de dos números grandes pasados.
    Tenga en cuenta: ¡los métodos no son estáticos!

    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));
    
       }
    }

    Salida de consola:

    
    222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222

Control de redondeo BigDecimal

Este tema está incluido en una sección aparte, ya que redondear números grandes y ajustarlos no es algo tan sencillo. Puede establecer el número de decimales de un número BigDecimalutilizando el setScale(). Por ejemplo, queremos establecer la precisión del número 111,5555555555 en tres decimales. Sin embargo, no podremos pasar el número 3 como argumento al método setScale()y así resolver nuestro problema. Como se mencionó anteriormente, BigDecimalestos son números para cálculos con mayor precisión. En su forma actual, nuestro número tiene 10 decimales. Queremos descartar 7 de ellos y dejar solo 3. Por lo tanto, además del número 3, debemos pasar como parámetro el modo de redondeo . Hay 8 modos de redondeo en total BigDecimal. ¡Bastante! Pero si realmente necesita ajustar la precisión de los cálculos en el programa, tendrá todo lo que necesita para ello. Entonces, aquí están los 8 modos de redondeo disponibles en BigDecimal:
  1. ROUND_CEILING- redondeando

    111.5555555555 -> setScale(3, ROUND_CEILING) -> 111.556
  2. ROUND_DOWN- descarga descarte

    111.5555555555 -> setScale(3, ROUND_DOWN) -> 111.555
  3. ROUND_FLOOR- redondeando hacia abajo

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

  4. ROUND_HALF_UP— redondear hacia arriba si el número después del punto decimal >= .5

    0.55 -> setScale(1, ROUND_HALF_UP) -> 0.6
    0.54 -> setScale(1, ROUND_HALF_UP) -> 0.5
  5. ROUND_HALF_DOWN— redondear hacia arriba si el número después del punto decimal > 0,5

    0.55 -> setScale(1, ROUND_HALF_DOWN) -> 0.5
    0.56 -> setScale(1, ROUND_HALF_DOWN) -> 0.6
  6. ROUND_HALF_EVEN— el redondeo dependerá del número a la izquierda del punto decimal. Si el número de la izquierda es par, el redondeo se realizará hacia abajo. Si el número a la izquierda del punto decimal es impar, se redondeará hacia arriba.

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

    El número a la izquierda del punto decimal (2) es par. El redondeo se produce hacia abajo. Como requerimos 0 decimales, el resultado será 2.

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

    El número a la izquierda del punto decimal (3) es impar. El redondeo se produce hacia arriba. Como requerimos 0 decimales, el resultado será 4.

  7. ROUND_UNNECCESSARY— se utiliza en los casos en los que es necesario pasar el modo de redondeo a algún método, pero el número no necesita redondeo. Si intenta redondear un número cuando el modo ROUND_UNNECCESSARY está configurado, se genera una excepción ArithmeticException.

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

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

Comparación de grandes números

Esta pregunta también es importante. Ya recordarás que el método se utiliza para comparar objetos en Java equals(). Lo proporciona el propio lenguaje (en el caso de las clases integradas de Java) o lo anula el programador. Pero en el caso de objetos de clase, no se recomienda BigDecimalutilizar métodos equals()de comparación. La razón de esto es que el BigDecimal.equals()método de dos números devuelve verdadero solo si los dos números tienen el mismo valor y escalaequals() : comparemos el comportamiento de los métodos y Doublee 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));

   }
}
Salida de consola:

true
false
Como puede ver, los números 1,5 y 1,50 en el caso de c BigDecimalresultaron ser desiguales. Esto sucedió precisamente debido a las características específicas del método equals()en la clase BigDecimal. Para una comparación más correcta de los dos, BigDecimales mejor utilizar el método 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));

   }
}
Salida de consola:

0
El método compareTo()devolvió 0, lo que significa igual a 1,5 y 1,50. ¡Este es el resultado con el que contábamos! :) Esto concluye nuestra lección de hoy. ¡Es hora de volver a las tareas! :)
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION