boolean
y char
, se dividen en los siguientes tipos:
- números enteros:
byte
,short
,int
ylong
; - punto flotante (también llamado números reales):
float
ydouble
.
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 BigInteger
y BigDecimal
.
BigInteger en Java
La clase JavaBigInteger
se 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
, Double
etc.), 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 BigInteger
con 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 BigInteger
con valores, respectivamente 0
, 1
y 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
-
operaciones con cálculo mod :
BigInteger firstValue = new BigInteger("-34"); BigInteger secondValue = new BigInteger("5"); BigInteger resultValue = firstValue.mod(secondValue); //1
-
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
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
, BigDecimal
es descendiente de una clase Number
y 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 constructoresBigDecimal
, 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
, double
e String
incluso 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 BigInteger
y establecemos el número de decimales.
Métodos BigDecimal
La claseBigDecimal
también contiene métodos para diversas operaciones aritméticas, pero BigInteger
no tiene métodos para trabajar con bits, como . Sin embargo, la característica principal BigDecimal
es 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
BigDecimal
por otroBigDecimal
, 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 interiorBigDecimal
podemos 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 BigDecimal
tiene constantes similares a las constantes BigInteger ZERO
, ONE
y TEN
. Aquí hay un enlace a la documentación . Y finalmente: como probablemente hayas notado, al realizar operaciones con objetos BigInteger
y 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.
GO TO FULL VERSION