JavaRush /Blog Java /Random-ES /BigInteger y BigDecimal

BigInteger y BigDecimal

Publicado en el grupo Random-ES
En Java, una aplicación se compone de clases y las clases se componen de métodos y variables. Las variables, a su vez, se dividen en primitivas y de referencia. BigInteger y BigDecimal - 1Hay 8 tipos de variables en Java y, excluyendo booleany char, se dividen en los siguientes tipos:
  • números enteros: byte, short, inty long;
  • punto flotante (también llamado números reales): floaty double.
Dentro de estos pequeños grupos, las diferencias existen sólo en el rango de valores que pueden contenerse (y, en consecuencia, el espacio ocupado por dicha variable varía). El mayor de los tipos de enteros es long, con un rango de -9223372036854775808 a 9223372036854775807. De los números de punto flotante, double, con un rango de 1.7e-308 a 1.7e+308. Puedes leer más sobre números reales en este artículo . Pero, ¿qué pasa si necesitamos almacenar números mayores que el rango aceptable? En este caso, necesitaremos BigIntegery BigDecimal.

BigInteger en Java

La clase Java BigIntegerse utiliza como analogía de valores enteros de longitud arbitraria que no tienen el límite de longitud de 64 bits. Además, es descendiente de la clase Number, como envoltorios estándar para tipos numéricos simples ( Integer, Long, Byte, Doubleetc.), por lo que tiene implementaciones de métodos que conducen a tipos simples:
BigInteger value = new BigInteger("32145");

int intValue = value.intValue();//32145

long longValue = value.longValue();//32145

double doubleValue = value.doubleValue();//32145.0
Inmediatamente vemos la creación de dicho objeto BigIntegercon nuestro valor pasado al constructor, pero en formato de cadena. Cabe destacar que tiene más de un diseñador, pero para todas las ocasiones. Si los tipos primitivos no se adaptan a la cantidad total de datos de BigInteger, los datos se truncarán al rango de ese tipo primitivo. Pero al mismo tiempo, existen análogos de estos métodos ( intValueExact(), longValueExact()etc.), con la única diferencia de que si el tipo simple al que se realiza la conversión no se adapta al rango de datos, se genera una excepción ArithmeticException .

Constantes BigInteger

Para uso interno, la clase tiene constantes:
BigInteger.ZERO
BigInteger.ONE
BigInteger.TEN
Estos son objetos constantes BigIntegercon valores, respectivamente 0, 1y 10.

Métodos BigInteger

Una de las principales características de esta clase es que está llena de métodos que implementan operaciones aritméticas estándar en Java. Por ejemplo:
  • operaciones de suma:

    BigInteger firstValue = new BigInteger("37995");
    BigInteger secondValue = new BigInteger("35466");
    BigInteger resultValue =  firstValue.add(secondValue);//73461
  • operaciones de multiplicación:

    BigInteger firstValue = new BigInteger("37995");
    BigInteger secondValue = new BigInteger("35466");
    BigInteger resultValue =  firstValue.multiply(secondValue);//1347530670
  • operaciones para encontrar el resto al dividir un número por otro:

    BigInteger firstValue = new BigInteger("37995");
    BigInteger secondValue = new BigInteger("35466");
    BigInteger resultValue =  firstValue.remainder(secondValue);//2529
  • obtener el valor absoluto de un número (es decir, módulo, sin signo):

    BigInteger firstValue = new BigInteger("-37995");
    BigInteger resultValue =  firstValue.abs();//37995
También existen métodos para operaciones más complejas (específicas):
  • operaciones con cálculo mod :

    BigInteger firstValue = new BigInteger("-34");
    BigInteger secondValue = new BigInteger("5");
    BigInteger resultValue = firstValue.mod(secondValue); //1
Hay varias variaciones diferentes de esta función:
  • obteniendo un número aleatorio y especificando el número de bits que utilizará el valor resultante:

    BigInteger firstValue = BigInteger.probablePrime(8, new Random());//211
    BigInteger secondValue = BigInteger.probablePrime(16, new Random());//42571
  • operaciones de desplazamiento bit a bit (este >> n)

    Desplazamiento a la izquierda:

    BigInteger firstValue = new BigInteger("5");
    BigInteger firstResultValue = firstValue.shiftLeft(3);//40

    Desplazamiento a la derecha:

    BigInteger secondValue = new BigInteger("34");
    BigInteger secondResultValue = secondValue.shiftRight(2); //8
Por supuesto, es mejor consultar la lista completa de métodos en la documentación . BigInteger y BigDecimal - 2

GranDecimal en Java

Cuando necesitamos un número real de longitud arbitraria, se utiliza la clase Java - BigDecimal. Por regla general, se utiliza para trabajar con finanzas en lugar de double, ya que ofrece más opciones de personalización. Me gusta y BigInteger, BigDecimales descendiente de una clase Numbery tiene métodos que devuelven el valor de un objeto como un tipo primitivo específico:
BigDecimal value = new BigDecimal(35563.3);

long longValue = value.longValue();//35563

double doubleValue = value.doubleValue();//35563.3
Como podemos ver al reducir a long, solo queda la parte entera y se descartan los decimales.

Constructores BigDecimal

Echaremos un vistazo más de cerca a los constructores BigDecimal, ya que la clase tiene una selección mucho más amplia de ellos. Hay constructores que te permiten establecer el valor de un objeto de diferentes maneras (pasando int, long, doublee Stringincluso BigInteger), y hay quienes lo permiten. establezca la configuración del objeto creado (métodos de redondeo, número de decimales):
BigDecimal firstValue = new BigDecimal("455656.545");//455656.545
Aquí todo está claro, establecemos directamente el valor y el número de decimales que queremos ver.
BigDecimal secondValue = new BigDecimal(3445.54);//3445.5399999999999636202119290828704833984375
Los resultados de este constructor pueden ser bastante impredecibles, porque especificamos double, que por su naturaleza es un tipo muy ambiguo. Por lo tanto, generalmente se recomienda su uso en un constructor String.
BigDecimal thirdValue = new BigDecimal(3445.554645675444, MathContext.DECIMAL32);//3445.555
Configuramos double, pero al mismo tiempo también configuramos un parámetro que describe la regla de redondeo (que contiene el número de decimales y el algoritmo de redondeo).
char[] arr = new String("455656.545").toCharArray();

BigDecimal fourthValue = new BigDecimal(arr, 2, 6);//5656.5
Establecemos una matriz de caracteres de qué elemento tomamos los valores para el objeto y cuántos de estos elementos tomamos.
BigDecimal fifthValue = new BigDecimal(new BigInteger("44554"), 3);//44.554
Tomamos un objeto ya existente BigIntegery establecemos el número de decimales.

Métodos BigDecimal

La clase BigDecimaltambién contiene métodos para diversas operaciones aritméticas, pero BigIntegerno tiene métodos para trabajar con bits, como . Sin embargo, la característica principal BigDecimales la flexibilidad para trabajar con números de coma flotante. Veamos algunas técnicas que nos dan el poder de dominar los números reales:
  • obtenemos la precisión (número de números):

    BigDecimal value = new BigDecimal("454334.34334");
    int result = value.precision();//11
  • establezca el número de decimales y la regla de redondeo:

    BigDecimal firstValue = new BigDecimal(3445.544445);
    
    BigDecimal secondValue = firstValue.setScale(3,BigDecimal.ROUND_CEILING);//3445.545

    A continuación veremos más de cerca las constantes para establecer reglas de redondeo.

  • dividir BigDecimalpor otro BigDecimal, indicando el número requerido de decimales y la regla de redondeo:

    BigDecimal firstValue = new BigDecimal("455656.545");
    
    BigDecimal secondValue = new BigDecimal(3445.544445);
    
    BigDecimal result = firstValue.divide(secondValue, 2,RoundingMode.DOWN);//132.24
  • mover un punto decimal hacia la derecha/izquierda un cierto número de lugares:

    BigDecimal value = new BigDecimal("455656.545");
    BigDecimal firstResult = value.movePointRight (2);//45565654.5
    BigDecimal secondResult = value.movePointLeft (2);//4556.56545
  • recortar ceros finales:

    BigDecimal value = new BigDecimal("45056.5000");
    BigDecimal result = value.stripTrailingZeros();//45056.5

    Si tenemos todos ceros en la parte real y también hay ceros en toda la parte (o no tenemos ningún decimal), entonces:

    BigDecimal value = new BigDecimal("450000.000");
    BigDecimal result = value.stripTrailingZeros();//4.5E+5

Reglas de redondeo BigDecimal

Para establecer reglas de redondeo, en su interior BigDecimalpodemos ver constantes especiales que describen algoritmos de redondeo: ROUND_UP- redondeo desde cero, redondeo hacia la parte real:
BigDecimal firstValue = new BigDecimal("2.578");
BigDecimal firstResult =  firstValue.setScale(1, BigDecimal.ROUND_UP );//2.6
BigDecimal secondValue = new BigDecimal("-2.578");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_UP );//-2.5
ROUND_DOWN— redondeo a cero, es decir, truncamiento de la parte real:
BigDecimal firstValue = new BigDecimal("2.578");
BigDecimal firstResult =  firstValue.setScale(1, BigDecimal.ROUND_DOWN  );//2.5
BigDecimal secondValue = new BigDecimal("-2.578");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_DOWN  );//-2.6
ROUND_CEILING— redondeando al infinito positivo. Es decir, si nuestro número es positivo, entonces -> ROUND_UP, si es negativo, entonces ->ROUND_DOWN
BigDecimal firstValue = new BigDecimal("2.578");
BigDecimal firstResult =  firstValue.setScale(1, BigDecimal.ROUND_CEILING);//2.6
BigDecimal secondValue = new BigDecimal("-2.578");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_CEILING);//-2.5
ROUND_FLOOR- redondear al infinito negativo, es decir, si nuestro número es positivo, entonces -> ROUND_DOWN, si es negativo, entonces ->ROUND_UP
BigDecimal firstValue = new BigDecimal("2.578");
BigDecimal firstResult =  firstValue.setScale(1, BigDecimal.ROUND_FLOOR);//2.5
BigDecimal secondValue = new BigDecimal("-2.578");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_FLOOR);//-2.6
Para el valor considerado, consideraremos este número más cercano con un decimal truncado como el vecino más cercano del número considerado. Por ejemplo, 2,43 estará más cerca de 2,4 que de 2,5, pero 2,48 estará más cerca de 2,5. ROUND_HALF_DOWN— redondeo al “vecino más cercano”. Si ambos vecinos están equidistantes de un valor particular, entonces se realiza el redondeo a cero. Equidistante es, por ejemplo, cuando el número que se redondea es 5, y está a la misma distancia de 0 y 10):
BigDecimal firstValue = new BigDecimal("2.58");
BigDecimal firstResult =  firstValue.setScale(1, BigDecimal.ROUND_HALF_DOWN );//2.6
BigDecimal secondValue = new BigDecimal("2.55");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_HALF_DOWN );//2.5
ROUND_HALF_UP— modo de redondeo hacia el “vecino más cercano”. Si ambos vecinos están equidistantes, se redondea hacia arriba (este es el mismo redondeo que nos enseñaron en la escuela):
BigDecimal firstValue = new BigDecimal("2.53");
BigDecimal firstResult =  firstValue.setScale(1, BigDecimal.ROUND_HALF_UP  );//2.5
BigDecimal secondValue = new BigDecimal("2.55");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_HALF_UP  );//2.6
ROUND_HALF_EVEN— redondear al “vecino más cercano” si ambos vecinos no son equidistantes. En este caso, si el número que se redondea va precedido de un número impar, se redondea hacia arriba, y si es par, se redondea hacia abajo:
BigDecimal firstValue = new BigDecimal("2222.2225");
BigDecimal secondValue = firstValue.setScale(3,BigDecimal.ROUND_HALF_EVEN );//2222.222
Obtenemos este resultado porque al redondear, 5 mira el número anterior 2, y al ver que es par, redondea hacia abajo. Pero si:
BigDecimal firstValue = new BigDecimal("2222.22255");
BigDecimal secondValue = firstValue.setScale(3,BigDecimal.ROUND_HALF_EVEN );//2222.223
Ese redondeo sube, ya que los últimos 5 miran el valor anterior y ven un número impar. Como resultado, el número se redondea a 6, después de lo cual también se redondea el siguiente 6. Pero el seis ya no mira el número de la izquierda, ya que el número está claramente más cerca hacia arriba y, como resultado, los últimos 2 aumentan en 1. ROUND_UNNECESSARY- se utiliza para comprobar que no es necesario redondear el número. Es decir, comprobamos que el número tenga el número requerido de decimales:
BigDecimal firstValue = new BigDecimal("2.55");
BigDecimal firstResult =  firstValue.setScale(2, BigDecimal.ROUND_UNNECESSARY);//2.55
Aquí está todo bien, el valor tiene dos dígitos y comprobamos que después del punto decimal solo quedan dos dígitos. Pero si:
BigDecimal secondValue = new BigDecimal("2.55");
BigDecimal secondResult = secondValue.setScale(1, BigDecimal.ROUND_UNNECESSARY);
Luego obtenemos - ArithmeticException, ya que el valor que se está probando excede el número especificado de decimales. Pero si verificamos dos decimales, pero en realidad hay uno allí, entonces no se generará la excepción y los dígitos que faltan simplemente se complementan con ceros:
BigDecimal thirdValue = new BigDecimal("2.5");
BigDecimal thirdResult = thirdValue.setScale(3, BigDecimal.ROUND_UNNECESSARY   );//2.500
También me gustaría señalar que y BigDecimaltiene constantes similares a las constantes BigInteger ZERO, ONEy TEN. Aquí hay un enlace a la documentación . Y finalmente: como probablemente hayas notado, al realizar operaciones con objetos BigIntegery BigDecimal, no cambiamos los antiguos, sino que siempre obtenemos otros nuevos. Esto nos dice que son immutable, es decir, inmutables después de su creación, al igual que String. En otras palabras, todos sus métodos no pueden cambiar el estado interno del objeto; como máximo, pueden devolver un nuevo objeto con los parámetros especificados por la función que estamos usando.
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION