¿Cuántos dígitos significativos tienen los flotantes y los dobles en Java?

81

¿Un flotador tiene 32 dígitos binarios y un doble tiene 64 dígitos binarios? La documentación era demasiado difícil de entender.

¿Todos los bits se traducen en dígitos significativos? ¿O la ubicación del punto decimal ocupa algunos de los bits?

Eamon Moloney
fuente
2
¿Todos esos bits se traducen en dígitos significativos? ¿O la ubicación del punto decimal ocupa algunos de los bits?
Eamon Moloney
@ user1774214 los números de punto flotante no están codificados en absoluto como enteros. echa un vistazo al enlace que te doy. Debe comprender, por ejemplo, que la precisión no es uniforme.
Denys Séguret
@dystroy No estoy seguro de lo que quieres decir con "la precisión no es uniforme". Tiene una precisión bastante uniforme de 53 y 24 bits, a menos que se refiera a desnormales.
Pascal Cuoq
2
@PascalCuoq hay más precisión para números más pequeños. A medida que cambia el exponente (o el punto flota), la mantisa sigue representando la misma cantidad de dígitos. Entonces, si el número es grande, la mantisa "no puede alcanzar" tanto los dígitos significativos más bajos, dando menos precisión.
Vituel
3
@Virtuel La precisión es de 53 bits. Eso es lo que llamamos precisión. Parece estar pensando en la precisión absoluta o algo así.
Pascal Cuoq

Respuestas:

105

flotante : 32 bits (4 bytes) donde se utilizan 23 bits para la mantisa (aproximadamente 7 dígitos decimales). Se utilizan 8 bits para el exponente, por lo que un flotante puede "mover" el punto decimal a la derecha oa la izquierda utilizando esos 8 bits. Si lo hace, evita almacenar muchos ceros en la mantisa, como en 0.0000003 (3 × 10 -7 ) o 3000000 (3 × 10 7 ). Se utiliza 1 bit como bit de signo.

doble : 64 bits (8 bytes) donde se utilizan 52 bits para la mantisa (aproximadamente 16 dígitos decimales). Se utilizan 11 bits para el exponente y 1 bit es el bit de signo.

Dado que estamos usando binario (solo 0 y 1), un bit en la mantisa es implícitamente 1 (tanto float como double usan este truco) cuando el número es distinto de cero.

Además, dado que todo está en binario (mantisa y exponentes), las conversiones a números decimales generalmente no son exactas. Números como 0.5, 0.25, 0.75, 0.125 se almacenan exactamente, pero 0.1 no. Como han dicho otros, si necesita almacenar centavos con precisión, no use float o double, use int, long, BigInteger o BigDecimal.

Fuentes:

http://en.wikipedia.org/wiki/Floating_point#IEEE_754:_floating_point_in_modern_computers

http://en.wikipedia.org/wiki/Binary64

http://en.wikipedia.org/wiki/Binary32

Marco
fuente
¿Qué quieres decir de 6 a 9? como puede cambiar así que si ejecuto un código que tiene 8 dígitos decimales como 0.000000001 varias veces, ¿obtendré resultados diferentes? ¿Es eso lo que quieres decir?
Aequitas
1
Algunos números se pueden representar de forma más exacta en binario que otros. Puede ver la diferencia en 0.125 (1/8, ocho es una potencia de dos) y 0.1 (1/10, diez no es una potencia de dos). El primero tiene más dígitos (decimales), pero se representa exactamente. Entonces, podría ser que un número con 6 dígitos decimales tenga errores de redondeo mayores que otro número con 8 dígitos.
marcus
9
15.9 dígitos decimales para doubley 7.2 para float, es decir, 15 y 7. Algunos números más grandes se pueden representar en cada caso, y ninguno de ellos se aplica a las fracciones, pero no hay un 'promedio' al respecto, y ninguna de sus fuentes dice de otra manera.
Marqués de Lorne
1
Si no le gusta la palabra promedio, proponga una edición. No fue agregado por mí en primer lugar, fue editado por otra persona ... (y realmente no vi la necesidad de esa edición).
Marcus
4
Curiosamente, en realidad hay un dígito más de precisión que el almacenado en la mantisa / significando. Se almacenan 23 y 52 bits para float y double, respectivamente, pero debido a que los números están normalizados, podemos asumir un 1 bit a la izquierda y luego dejarlo fuera. Es por esto que la precisión efectiva es de 24 y 53 bits, respectivamente. Las precisiones decimales precisas se calculan log10 (2 ^ 24) = 7.22 y log10 (2 ^ 53) = 15.95
Georgie
32

Un flotante de 32 bits tiene aproximadamente 7 dígitos de precisión y un doble de 64 bits tiene aproximadamente 16 dígitos de precisión

Respuesta larga:

Los números de coma flotante tienen tres componentes:

  1. Un bit de signo, para determinar si el número es positivo o negativo.
  2. Un exponente, para determinar la magnitud del número.
  3. Una fracción, que determina qué tan lejos entre dos valores de exponente está el número. Esto a veces se denomina "el significado, la mantisa o el coeficiente".

Esencialmente, esto funciona sign * 2^exponent * (1 + fraction). El "tamaño" del número, su exponente, es irrelevante para nosotros, porque solo escala el valor de la fracción. Sabiendo que log₁₀(n)da el número de dígitos de n, † podemos determinar la precisión de un número de coma flotante con log₁₀(largest_possible_fraction). Debido a que cada bit en un flotante almacena 2 posibilidades, un número binario de nbits puede almacenar un número hasta 2ⁿ - 1(un total de 2ⁿ valores donde uno de los valores es cero). Esto se vuelve un poco más complicado, porque resulta que los números de punto flotante se almacenan con un bit menos de fracción de la que pueden usar, porque los ceros se representan de manera especial y todos los números distintos de cero tienen al menos un bit binario distinto de cero. ‡

Combinando esto, los dígitos de precisión para un número de punto flotante son log₁₀(2ⁿ), donde nes el número de bits de la fracción del número de punto flotante. Un flotante de 32 bits tiene 24 bits de fracción para ≈7,22 dígitos decimales de precisión, y un doble de 64 bits tiene 53 bits de fracción para ≈15,95 dígitos decimales de precisión.

Para obtener más información sobre la precisión del punto flotante, es posible que desee leer sobre el concepto de una máquina épsilon .


† Por lo n ≥ 1menos, para otros números, su fórmula se parecerá más ⌊log₁₀(|n|)⌋ + 1.

‡ "Esta regla se denomina de forma diversa convención de bits inicial, convención de bits implícita o convención de bits ocultos". ( Wikipedia )

9999 años
fuente
17

De la especificación java :

Los tipos de coma flotante son flotante y doble, que están asociados conceptualmente con los valores y operaciones de formato de precisión simple de 32 bits y de 64 bits de precisión doble IEEE 754, como se especifica en el estándar IEEE para aritmética de coma flotante binaria, ANSI / IEEE Estándar 754-1985 (IEEE, Nueva York).

Como es difícil hacer algo con números sin comprender los conceptos básicos de IEEE754, aquí hay otro enlace .

Es importante comprender que la precisión no es uniforme y que este no es un almacenamiento exacto de los números como se hace para los enteros.

Un ejemplo :

double a = 0.3 - 0.1;
System.out.println(a);          

huellas dactilares

0.19999999999999998

Si necesita precisión arbitraria (por ejemplo, con fines financieros), es posible que necesite Big Decimal .

Denys Séguret
fuente
7

Una respuesta matemática normal.

Entendiendo que un número de punto flotante se implementa como algunos bits que representan el exponente y el resto, la mayoría para los dígitos (en el sistema binario), uno tiene la siguiente situación:

Con un exponente alto, digamos 10²³ si se cambia el bit menos significativo, aparece una gran diferencia entre dos números visibles adyacentes. Además, el punto decimal en base 2 hace que muchos números en base 10 solo se puedan aproximar; 1/5, siendo 1/10 números infinitos.

Entonces, en general : los números de punto flotante no deben usarse si le interesan los dígitos significativos. Para cantidades monetarias con cálculo, e, a, mejor use BigDecimal .

Para la física, los dobles de coma flotante son adecuados, los flotadores casi nunca. Además, la parte de punto flotante de los procesadores, la FPU, puede incluso utilizar un poco más de precisión internamente.

Joop Eggen
fuente
3

Los números de coma flotante se codifican utilizando una forma exponencial, es m * b ^ edecir, no como enteros en absoluto. La pregunta que haga sería significativa en el contexto de números de punto fijo . Existen numerosas bibliotecas aritméticas de coma fija disponibles.

Respecto a la aritmética de coma flotante: El número de dígitos decimales depende de la presentación y del sistema numérico. Por ejemplo, hay números periódicos ( 0.33333) que no tienen una presentación finita en decimal pero sí tienen una en binario y viceversa.

También vale la pena mencionar que los números de coma flotante hasta cierto punto sí tienen una diferencia mayor que uno, es decir , value + 1rendimientos value, ya value + 1que no se pueden codificar usando m * b ^ e, where m, by etienen una longitud fija. Lo mismo ocurre con valores menores a 1, es decir, no todos los puntos de código posibles tienen la misma distancia.

Debido a esto, no hay precisión de ndígitos exactos como con los números de punto fijo, ya que no todos los números con ndígitos decimales tienen una codificación IEEE.

Hay un documento casi obligatorio que debería leer entonces y que explica los números de punto flotante: Lo que todo científico informático debería saber sobre la aritmética de punto flotante .

scravy
fuente
2
+1 por mencionar "Lo que todo científico informático debería saber sobre la aritmética de punto flotante". Sin embargo, vale la pena señalar que cada número que tiene una representación de fracción binaria finita también tiene una representación decimal finita. El problema solo pasa de decimal a binario.
Patricia Shanahan
1

Mire Float.intBitsToFloaty Double.longBitsToDouble, que explica cómo los bits se corresponden con los números de punto flotante. En particular, los bits de una normal se floatparecen a

 s * 2^exp * 1.ABCDEFGHIJKLMNOPQRSTUVW

donde A ... W son 23 bits - 0 y 1 - que representan una fracción en binario - s es +/- 1, representado por un 0 o un 1 respectivamente, y exp es un entero de 8 bits con signo.

Louis Wasserman
fuente