|
|
Publicado en 7/4/2015 14:53:05
|
|
|

En Java se proporcionan clases de operación para números grandes, concretamente la clase java.math.BinInteger y la clase java.math.BigDecimal. Estas dos clases se utilizan para computación de alta precisión, siendo la clase BigInteger la clase de procesamiento para enteros grandes y la clase BigDecimal la clase de procesamiento para números grandes y pequeños. A continuación presentamos la clase BigDecimal: La implementación de BigDecimal aprovecha BigInteger, excepto que BigDecimal añade el concepto de decimales. Los datos generales de tipo flotante y doble tipo solo pueden usarse para cálculos científicos o de ingeniería, porque en la computación comercial la precisión numérica requerida es relativamente alta, por lo que se utiliza la clase java.math.BigDecimal, que soporta cualquier precisión de puntos fijos y puede usarse para calcular valores de moneda con precisión. A continuación presentaremos brevemente su uso con ejemplos
java.math.BigDecimal
Hoy he escrito un programa sobre conversión binaria y decimal con referencia al libro de texto, y el algoritmo del programa no es difícil, pero tras escribir, descubrí que, sea de 2 a 10 o de 10 a 2, no es una buena conversión para números mayores a 2.100 millones, es decir, más que el rango de enteros. se convertirá en 0. Los libros de referencia han encontrado que usar BigInteger resuelve este problema. Así que busqué el JDK, lo probé varias veces y finalmente lo escribí con éxito. La experiencia de uso es la siguiente:
1. BigInteger pertenece a java.math.BigInteger, así que importa esta clase antes de cada uso. A veces, se me olvidaba importar al principio, así que el prompt no se encuentra en el prompt constante.
2. Existen muchos métodos de construcción, pero ahora se utilizan ocasionalmente: BigEnter(val de cadenas) Convierte la representación decimal de la cadena de BigInteger a BigInteger. BigEnter(String val, int radix) Convierte la representación de cadena del BigInteger para la cardinalidad especificada en el BigInteger. Para convertir 2 de tipo int a tipo BigEnter, escribe BigInteger dos = nuevo BigEnter("2"); Nota 2: no se pueden omitir las comillas dobles
3. La clase BigInteger simula todas las operaciones matemáticas de tipo int, como add()=="+", divide()=="-", etc., pero hay que tener en cuenta que su contenido no puede usarse directamente para operaciones matemáticas al realizar operaciones matemáticas, y debe utilizar sus métodos internos. Y su operando también debe ser de tipo BigInteger. Por ejemplo: two.add(2) es una operación incorrecta porque 2 no se convierte en un tipo BigEnter.
4. Cuando quieras exportar los resultados del cálculo, deberías usar el método .toString para convertirlo en una cadena decimal, como se detalla a continuación: String toString() Devuelve la representación decimal de la cadena de este BigInteger. Método de salida: System.out.print(two.toString());
5. Explica las tres funciones utilizadas. BigInteger resto(BigInteger val) Devuelve un GrandInteger con un valor de (este % val). Negación BigInteger () BigInteger devuelve un valor de (-this). int compareTo(BigInteger val) Compara este BigInteger con el BigInteger especificado. El resto se usaba para encontrar el resto. Negar convierte el operando en lo opuesto. La comparación se explica en detalle de la siguiente manera: compareTo
public int compareTo(BigInteger val)
Compara este BigInteger con el BigInteger especificado. Este método es preferido para cada uno de los seis operadores de comparación booleanos (<, ==, >, >=, !=, <=). La instrucción sugerida para realizar estas comparaciones es: (x.compareTo(y) <op> 0), donde es <op> uno de los seis operadores de comparación.
Especificador: interfaz<BigInteger> Comparable
Parámetros: val - El BigInteger que compara este BigInteger con él. Atrás:
Título Implementando cálculos precisos de números de coma flotante en Java Modificación AYellow (original) Palabras clave Java cálculo preciso de números de coma flotante
Pregunta planteada: ¿Qué veríamos si compiláramos y ejecutáramos el siguiente programa? clase pública Test{ public static void main(String args[]){ System.out.println(0.05+0.01); System.out.println(1.0-0.42); System.out.println(4.015*100); System.out.println(123.3/100); } };
¡Has leído bien! El resultado es, efectivamente 0.060000000000000005 0.5800000000000001 401.49999999999994 1.2329999999999999
No se pueden operar tipos simples de flotación y doble en Java. Este problema no solo se encuentra en Java, sino también en muchos otros lenguajes de programación. En la mayoría de los casos, los cálculos son precisos, pero puedes intentarlo varias veces más (puedes hacer un bucle) para intentar errores como el anterior. Ahora por fin entiendo por qué existe un código BCD. Este problema es bastante serio: si tienes 9,99999999999999999999 yuanes, tu ordenador no pensará que puedes comprar 10 yuanes de mercancía. Algunos lenguajes de programación proporcionan tipos de moneda especializados para manejar esta situación, pero Java no. Ahora veamos cómo arreglar esto.
Redondeo Nuestra primera reacción es hacer redondeos. El método de ronda en la clase de Matemáticas no puede configurarse para mantener unos pocos decimales, solo podemos hacer esto (mantener dos lugares): ronda doble pública (valor doble){ return Math.round(value*100)/100.0; }
Desafortunadamente, el código anterior no funciona; pasar la 4.015 a este método devolverá la 4.01 en lugar de la 4.02, como vimos arriba 4.015*100=401.499999999999994 Por lo tanto, si queremos hacer redondeos precisos, no podemos usar tipos simples para realizar ninguna operación java.text.DecimalFormat tampoco resuelve este problema: System.out.println(nuevo java.text.DecimalFormat("0.00").format(4.025)); La salida es de 4,02
BigDecimal Este principio también se menciona en el libro "Java Efectivo"; float y double solo pueden usarse para cálculos científicos o de ingeniería, y en computación empresarial necesitamos usar java.math.BigDecimal. Hay 4 formas de construir BigDecimal, no nos importan las dos que se hacen con BigInteger, así que hay dos más, que son: BigDecimal (doble val) Traduce un doble en un BigDecimal. BigDecimal(val de cadenas) Traduce la representación de cadena de un BigDecimal a una BigDecimal.
La API se describe brevemente y suele ser más fácil de usar. Quizá lo usemos sin siquiera pensarlo, ¿cuál será el problema? Cuando algo salió mal, descubrí que había un párrafo en la descripción detallada de cuál de los métodos anteriores era suficiente: Nota: los resultados de este constructor pueden ser algo impredecibles. Se podría suponer que el nuevo BigDecimal(.1) es exactamente igual a 0,1, pero en realidad es igual a .1000000000000000055511151231257827021181583404541015625. Esto es así porque 0,1 no puede representarse exactamente como un doble (o, de hecho, como una fracción binaria de cualquier longitud finita). Por tanto, el valor largo que se está pasando al constructor no es exactamente igual a 0,1, sin importar las apariencias. El constructor (String), en cambio, es perfectamente predecible: new BigDecimal(".1") es exactamente igual a 0,1, como cabría esperar. Por lo tanto, generalmente se recomienda que el constructor (String) se utilice en lugar de este.
Resulta que si necesitamos calcular con precisión, tenemos que usar String para crear BigDecimal! El ejemplo del libro Effective Java usa String para crear BigDecimal, pero el libro no enfatiza esto, lo que puede ser un pequeño error.
Solución Ahora que hemos resuelto este problema, el principio es usar BigDecimal y asegurarse de usar String. Pero imagina que si queremos hacer una operación de suma, primero tenemos que convertir dos números de coma flotante a String, luego crear un BigDecimal, llamar al método de suma en uno de ellos, pasar el otro como argumento y después convertir el resultado de la operación (BigDecimal) en un número de coma flotante. ¿Puedes soportar un proceso tan tedioso? A continuación proporcionamos una clase de herramienta, Arith, para simplificar la operación. Ofrece los siguientes métodos estáticos, incluyendo suma, resta, multiplicación y división, y redondeo: Doble Adición estática pública (doble v1, doble v2) Public Static Double Sub(doble v1, doble v2) Estática pública doble mul (doble v1, doble v2) Doble div estático público (doble v1, doble v2) Doble div estático público (doble v1, doble v2, escala INT) Doble ronda estática pública (doble v, escala INT)
Apéndice
Archivo fuente Arith.java:
importar java.math.BigDecimal; /** * Dado que los tipos simples de Java no pueden realizar operaciones de coma flotante con precisión, esta clase de herramientas proporciona multas * Operaciones exactas en punto flotante, incluyendo suma, resta, multiplicación, división y redondeo. */
clase pública Arith{
Precisión por defecto de la operación por división Privado estático final de la DEF_DIV_SCALE = 10;
Esta clase no puede ser instanciada soldado Arith(){ }
/** * Proporciona operaciones de suma precisas. * @param se añade v1 * @param adición v2 * @return La suma de los dos parámetros */
Public Static Double Add(Double v1,Double V2){ BigDecimal b1 = nuevo BigDecimal(Double.toString(v1)); BigDecimal b2 = nuevo BigDecimal(Double.toString(v2)); return b1.add(b2).doubleValue(); }
/** * Proporciona operaciones de restrata precisas. * @param se resta v1 * @param v2 menos * @return La diferencia entre los dos parámetros */
public static double sub(double v1,double v2){ BigDecimal b1 = nuevo BigDecimal(Double.toString(v1)); BigDecimal b2 = nuevo BigDecimal(Double.toString(v2)); return b1.subtract(b2).doubleValue(); }
/** * Proporciona operaciones de multiplicación precisas. * @param v1 se multiplica * @param multiplicador v2 * @return El producto de los dos parámetros */
Public Static Double Mul(Double v1,Double V2){ BigDecimal b1 = nuevo BigDecimal(Double.toString(v1)); BigDecimal b2 = nuevo BigDecimal(Double.toString(v2)); return b1.multiply(b2).doubleValue(); }
/** * Proporciona operaciones de división (relativamente) precisas cuando ocurre una división inagotable * 10 decimales y los siguientes dígitos se redondean. * @param v1 se divide * @param divisor v2 * @return El cociente de los dos parámetros */
Public Static Double Div(Double V1,Double V2){ devolución div(v1,v2,DEF_DIV_SCALE); }
/** * Proporciona operaciones divisionales (relativamente) precisas. Cuando ocurre una situación inagotable, se indica mediante el parámetro de escala * Determinar la precisión y los números posteriores se redondearán. * @param v1 se divide * @param divisor v2 * @param escala indica que debe ser precisa con unos pocos decimales. * @return El cociente de los dos parámetros */
Public Static Double Div(double v1,double v2,int scale){ if(scale<0){ lanzar nuevo IllegalArgumentException( "La escala debe ser un entero positivo o cero"); } BigDecimal b1 = nuevo BigDecimal(Double.toString(v1)); BigDecimal b2 = nuevo BigDecimal(Double.toString(v2)); return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue(); }
/** * Proporciona un redondeo decimal preciso. * @param v requiere redondear números * @param escala se reserva después del punto decimal * @return Resultados redondeados */
Ronda doble estática pública (doble v,int escala){ if(scale<0){ lanzar nuevo IllegalArgumentException( "La escala debe ser un entero positivo o cero"); } BigDecimal b = nuevo BigDecimal(Double.toString(v)); BigDecimal uno = nuevo BigDecimal("1"); return b.divide(uno,scale,BigDecimal.ROUND_HALF_UP).doubleValue(); } }; |
Anterior:Es mejor no poner una cuerda cuyo significado es clave primariaPróximo:Diferencias y conexiones entre JDK, JRE, JVM
|