Descripción del problema
Cuando se usa Java para calcular los números de puntos flotantes en el proyecto, se encontró que para cálculos como 4.015*100, el resultado no fue el esperado 401.5, sino 401.4999999999999999999999999999994. Un número tan largo de dígitos es hostil para la visualización.
Causa del problema: representación del número de punto flotante
Después de consultar información relevante, descubrí que la razón es que los números de puntos flotantes en la computadora no pueden expresarse completamente con precisión. Por ejemplo, para un doble tipo 38414.4, la computadora lo almacena así:
Convertir a binario: 100101100001110.01100110011001100110011001100110011001100
Transformar a un tema
Aprenda método de conteo: 1.0010110000111001100110011001100110011001100110011001100110011001100 × 2^15
El formato de codificación doble es el siguiente:
Double Sign Bit 1 dígito Código de etapa de 11 dígitos Mantissa 52 dígitos
Bit del símbolo: el número positivo es 0
Código de pedido: 15 es un número positivo, por lo que el bit más alto es 1, el bit más bajo es menos 1, que es 10000001110
MANTISMA: Retire el 1 de la broca más alto, que es 00101100111001100110011001100110011001100110011001100
Combinado, la codificación final es: 0 1000001110 001011001100110011001100110011001100110011001100110011001100
Desde aquí, podemos ver que la razón principal es que la codificación binaria hace que la parte fraccional sea imposible de expresar completamente exactamente, como 0.4 = 0.25 + 0.125 + ..., que solo puede estar infinitamente cerca. Por lo tanto, se producirán errores de precisión al calcular los números de puntos flotantes.
Solución: alta precisión
BigDecimal en Java puede admitir operaciones de número de puntos flotantes con precisión arbitraria. En el libro "Java efectivo", se recomienda que Float y Double se usen para cálculos científicos o cálculos de ingeniería, mientras que Java.Math.BigDecimal se usa en cálculos comerciales.
Hay muchos métodos de construcción para BigDecimal, como BigDecimal (doble) y BigDecimal (cadena). Cabe señalar que los parámetros de construcción son de tipo de cadena para garantizar que la precisión no se pierda, porque el tipo doble en sí es incompletamente preciso. Por lo tanto, debe escribirse de la siguiente manera: BigDecimal ("0.02").
Las operaciones básicas de doble tipo se pueden encontrar en BigDecimal. Además, BigDecimal también se puede usar para formatear la salida con NumberFormat.
BigDecimal generará nuevos objetos BigDecimal al realizar operaciones, por lo que traerá más sobrecarga de rendimiento en comparación con el doble.
Un estudio preliminar sobre la implementación de alta precisión
Entonces, ¿cómo puede BigDecimal representar una precisión arbitraria? Aquí hay solo un análisis preliminar.
Primero, veamos la implementación de BigInteger. El tipo de int ordinario es de 32 bits, por lo que hay una limitación de rango. Biginteger tiene la variable miembro int [] mag, de modo que la matriz int más larga hace posible representar enteros de cualquier tamaño.
Veamos la implementación de BigDecimal. Su introducción oficial dice que cualquier BigDecimal puede representarse como una escala de valor × 10^-10^. UnscaledValue es un entero de cualquier tamaño, correspondiente a la variable de miembro BigInteger Intval en el código fuente; La escala es el orden, correspondiente a la escala Variable int en el código fuente. De esta manera, BigDecimal se implementa en base a BigInteger.
Lo anterior es la solución al problema de precisión del punto flotante en Java presentada por el editor. Espero que te sea útil. Si tiene alguna pregunta, déjame un mensaje.