Los Java double
están en formato IEEE-754 , por lo que tienen una fracción de 52 bits; entre dos potencias adyacentes de dos (incluida una y excluida la siguiente), habrá 2 double
elevado a la 52 potencia s diferentes (es decir, 4503599627370496 de ellas). Por ejemplo, ese es el número de double
s distintos entre 0.5 incluido y 1.0 excluido, y exactamente ese número también se encuentra entre 1.0 incluido y 2.0 excluido, y así sucesivamente.
Contar doubles
entre 0.0 y 1.0 es más difícil que hacerlo entre potencias de dos, porque hay muchas potencias de dos incluidas en ese rango y, además, uno se mete en los espinosos temas de los números desnormalizados. 10 de los 11 bits de los exponentes cubren el rango en cuestión, por lo que, incluidos los números desnormalizados (y creo que algunos tipos deNaN
) tendrías 1024 veces la double
s entre potencias de dos, no más que 2**62
en total de todos modos . Excluyendo los & c desnormalizados, creo que el recuento sería 1023 veces 2**52
.
Para un rango arbitrario como "100 a 100.1" es aún más difícil porque el límite superior no se puede representar exactamente como a double
(no es un múltiplo exacto de ninguna potencia de dos). Como una práctica aproximación, dado que la progresión entre potencias de dos es lineal, se podría decir que dicho rango es0.1 / 64
el intervalo entre las potencias circundantes de dos (64 y 128), por lo que esperaría aproximadamente
(0.1 / 64) * 2**52
distintos double
s - que viene a 7036874417766.4004
... más o menos uno o dos ;-).
2**64
posibles valores dobles (ya que es un tipo de 64 bits), y aparentemente una ENORME proporción de esos valores se encuentra entre0..1
?Todo
double
valor cuya representación está entre0x0000000000000000
y se0x3ff0000000000000
encuentra en el intervalo [0.0, 1.0]. Eso es (2 ^ 62 - 2 ^ 52) valores distintos (más o menos un par dependiendo de si cuenta los puntos finales).El intervalo [1.0, 2.0] corresponde a representaciones entre
0x3ff0000000000000
y0x400000000000000
; eso es 2 ^ 52 valores distintos.El intervalo [100.0, 101.0] corresponde a representaciones entre
0x4059000000000000
y0x4059400000000000
; eso es 2 ^ 46 valores distintos.No hay dobles entre 10 ^ 100 y 10 ^ 100 + 1 . Ninguno de esos números se puede representar con precisión doble, y no hay dobles que se encuentren entre ellos. Los dos números de doble precisión más cercanos son:
y
fuente
Otros ya han explicado que hay alrededor de 2 ^ 62 dobles en el rango [0.0, 1.0].
(No es realmente sorprendente: hay casi 2 ^ 64 dobles finitos distintos, de los cuales la mitad son positivos, y aproximadamente la mitad de los que son <1,0).
Pero menciona generadores de números aleatorios: tenga en cuenta que un generador de números aleatorios que genere números entre 0,0 y 1,0 no puede, en general, producir todos estos números; normalmente solo producirá números de la forma n / 2 ^ 53 con n un entero (consulte, por ejemplo, la documentación de Java para nextDouble ). Por lo tanto, generalmente solo hay alrededor de 2 ^ 53 (+/- 1, según los puntos finales que se incluyan) valores posibles para la
random()
salida. Esto significa que la mayoría de los dobles en [0.0, 1.0] nunca se generarán.fuente
El artículo Nuevas matemáticas de Java, Parte 2: Números de punto flotante de IBM ofrece el siguiente fragmento de código para resolver esto (en flotantes, pero sospecho que también funciona para dobles):
Tienen este comentario al respecto:
fuente
float
, nodouble
-float
tienen una fracción de 23 bits, por lo que2**23 -> 8388608
valores diferentes entre potencias adyacentes de dos (la parte "inclusiva" por supuesto significa que tienes que contar una más, la siguiente potencia de dos).double
s tienen fracciones de 52 bits!double
equivalente y pensé "Oye, responderé mi propia pregunta en unos 5 minutos ..."double
potencias adyacentes de dos tomaría aproximadamente 52 días (println
por supuesto, es muy poco probable que funcione tan rápido sin importar qué, así que supongamos que una declaración desaparece ;-). Creo que es factible tomar un año o menos en una máquina potente pero realista ;-).Consulte el artículo de wikipedia para obtener más información.
fuente
1
es un error ya que el bit oculto es siempre uno - por lo tanto,2^52
, no2^53
distintos valores (entre los poderes adyacentes de dos, uno y se incluye la siguiente excluidos - No ! Entre 0,0 y 1,0).El doble de Java es un número IEEE 754 binary64.
Esto significa que debemos considerar:
Esto básicamente significa que hay un total de 2 ^ 62-2 ^ 52 + 1 de posibles representaciones dobles que, según el estándar, están entre 0 y 1. Tenga en cuenta que 2 ^ 52 + 1 es para eliminar los casos de los no normalizados. números.
Recuerde que si la mantisa es positiva pero el exponente es negativo, el número es positivo pero menor que 1 :-)
Para otros números es un poco más difícil porque los números enteros de borde pueden no ser representables de manera precisa en la representación IEEE 754, y porque hay otros bits usados en el exponente para poder representar los números, por lo que cuanto mayor es el número, menor los diferentes valores.
fuente