1. Introducción
Para tomar prestadas las palabras del libro "Java efactiva", los principales objetivos de diseño del flotador y los tipos dobles son para la informática científica y la informática de ingeniería. Realizan operaciones de puntos flotantes binarios, que están cuidadosamente diseñadas para proporcionar una aproximación rápida más precisa sobre el rango numérico de área amplia. Sin embargo, no proporcionan resultados completamente precisos y no deben usarse en situaciones en las que se requieran resultados precisos. Sin embargo, los cálculos comerciales a menudo requieren resultados precisos, y BigDecimal es útil en este momento.
2. Introducción a BigDecimal
BigDecimal consiste en un valor entero no escala de cualquier precisión y una escala entera de 32 bits. Si es cero o positivo, la escala es el número de dígitos después del punto decimal. Si se trata de un número negativo, multiplique el valor no escala del número por una potencia de escala negativa de 10. Por lo tanto, el valor representado por BigDecimal es (sin calificar el valor × 10 a escala).
3. Código de prueba
3.1 Constructor (los tipos de parámetros de prueba principales son dos constructores comunes con doble y cadena)
La copia del código es la siguiente: BigDecimal Adouble = new BigDecimal (1.22);
System.out.println ("Construye con un valor doble:" + Adouble);
BigDecimal Astring = new BigDecimal ("1.22");
System.out.println ("Construye con un valor de cadena:" + astring);
¿Cuál crees que será la salida? Si no cree que el primero emitirá 1.22, felicitaciones por la respuesta correctamente, el resultado de la salida es el siguiente:
Copie el código de la siguiente manera: Construya con un doble valor: 1.21999999999999999973335464740899624302983283996582031255
construir con un valor de cadena: 1.22
Descripción de JDK:
1. Los resultados del método de construcción con el tipo de parámetro doble son impredecibles. Algunas personas podrían pensar que el BigDecimal creado al escribir NewBigDecimal (0.1) en Java es exactamente igual a 0.1 (valor sin escala 1, cuya escala es 1), pero en realidad es igual a 0.10000000000000000000000000555511151231257827021181583404541015625. Esto se debe a que 0.1 no se puede expresar con precisión como un doble (o para este caso no puede expresarse como cualquier decimal binario de longitud finita). De esta manera, el valor pasado en el método de construcción no será exactamente igual a 0.1 (aunque es una superficie igual a ese valor).
2. Por otro lado, el método de construcción de cadenas es completamente predecible: escribir a newBigDecimal ("0.1") creará un BigDecimal, que es exactamente igual al 0.1 esperado. Por lo tanto, en comparación, generalmente se recomienda usar el constructor de cadenas primero.
3. Cuando el doble debe usarse como fuente de BigDecimal, tenga en cuenta que este constructor proporciona una conversión precisa; No proporciona el mismo resultado que las siguientes operaciones: primero use el método Double.ToString (doble) y luego use el constructor BigDecimal (String) para convertir el doble en cadena. Para obtener el resultado, use el método estático de valor (doble).
3.2 Operación de adición
La copia del código es la siguiente: BigDecimal a = new BigDecimal ("1.22");
System.out.println ("Construye con un valor de cadena:" + a);
BigDecimal b = new BigDecimal ("2.22");
A.Add (b);
System.out.println ("Aplus B es:" + A);
Es fácil pensar que saldrá:
Copie el código de la siguiente manera: Construya con un StringValue: 1.22
A Plus B es: 3.44
Pero de hecho, un plus B es: 1.22
4. Análisis del código fuente
4.1 Método ValorOf (DoubleVal)
Copie el código de la siguiente manera: public static static BigDecimal Value de (Double Val) {
// Recordatorio: un doble retorno de doble '0.0', por lo que no podemos Sardfastpath
// para usar el cero constante. Esto podría ser lo suficientemente importante para
// justificar un enfoque de fábrica, un caché o algunos privados
// constantes, más tarde.
returnnew bigDecimal (doble.toString (val)); // Consulte el tercer punto en 3.1 sobre la descripción JDK
}
4.2 Método Agregar (BigDecimal Augend)
public BigDecimal add (BigDecimal Augend) {long xs = this.intcompact; //BigDecimal represented by an integer number, for example a has an intCompact value of 122 long ys = augend.intCompact;//Same as above BigInteger fst = (this.intCompact !=INFLATED) ?null : this.intVal;//Initialize the value of BigInteger, intVal is a property of BigInteger type BigInteger snd =(augend.intCompact ! = Inflado)? Nulo: augend.intval; int rscale = this.scale; // Los lugares decimales largos sdiff = (long) rscale - augend.scale; // La diferencia entre los lugares decimales if (sdiff! = 0) {// Los lugares decimales con los lugares más decimales son el resultado si (sdiff <0) {int rain = checkscale (-sdiff); rscale = augend.scale; if (xs == inflado || (xs = longmultiplypowerten (xs, criar)) == inflado) fst = bigmultiplypowerten (Raise); } else {int Raise = augend.Checkscale (sdiff); if (ys == inflado || (ys = longmultiplypowerten (ys, criar)) == inflado) snd = augend.bigmultiplypowerten (criar); }} if (xs! = Infled && ys! = inflado) {long sum = xs + ys; if (((((sum ^ xs) y (sum ^ ys)))> = 0l) // juzga si hay algún desbordamiento. Return bigDecimal.ValueOf (suma, rcale); // return bigDecimal instancia obtenida usando el método de fábrica estática de BigDecimal} if (fst == null) fst = bigInteger.valueOf (xs); // Método de fábrica de Biginteger If (snd == null) snd = bigInteger.valueOf (ys); Biginteger sum = fst.add (snd); return (fst.signum == snd.signum)? New BigDecimal (suma, inflada, rcale, 0): nuevo bigDecimal (suma, compactvalfor (suma), rcale, 0); // devuelve el objeto BigDecimal obtenido por otros métodos de construcción}Lo anterior es solo un análisis del código fuente de adición. La resta, la multiplicación y la división realmente devuelven un nuevo objeto BigDecimal. Debido a que Biginteger y BigDecimal son inmutables, se generará un nuevo objeto al realizar cada paso de operación, por lo que A.Add (b); Aunque se realiza la operación de adición, A no guarda el valor después de la operación de adición. El uso correcto debe ser a = a.Add (b);
5. Resumen
(1) Los cálculos comerciales usan BigDecimal.
(2) Intente usar constructores con una cadena de tipo de parámetro.
(3) Bigdecimals son inmutables. Al realizar cada paso de operación, se generará un nuevo objeto. Por lo tanto, al realizar la adición, la resta, la multiplicación y la división, debe guardar el valor después de la operación.
(4) A menudo tendemos a ignorar algunos detalles de implementación del JDK subyacente, lo que resulta en errores, por lo que debemos prestar más atención.
Referencia: Clase BigDecimal