Os Java double
s estão no formato IEEE-754 , portanto, eles têm uma fração de 52 bits; entre quaisquer duas potências adjacentes de dois (incluindo uma e exclusiva da próxima), haverá, portanto, 2 elevado à 52ª potência double
s diferentes (ou seja, 4503599627370496 deles). Por exemplo, esse é o número de double
s distintos entre 0,5 incluídos e 1,0 excluídos, e exatamente esse número também está entre 1,0 incluído e 2,0 excluídos e assim por diante.
Contar doubles
entre 0,0 e 1,0 é mais difícil do que entre potências de dois, porque há muitas potências de dois incluídas nessa faixa e, também, entra-se nas questões espinhosas dos números desnormalizados. 10 dos 11 bits dos expoentes cobrem o intervalo em questão, então, incluindo números desnormalizados (e eu acho que alguns tipos NaN
), você teria 1024 vezes o double
s entre potências de dois - não mais do que 2**62
no total de qualquer maneira . Excluindo o desnormalizado etc., acredito que a contagem seria de 1.023 vezes 2**52
.
Para um intervalo arbitrário como "100 a 100,1" é ainda mais difícil porque o limite superior não pode ser representado exatamente como a double
(não sendo um múltiplo exato de qualquer potência de dois). Como uma aproximação útil, uma vez que a progressão entre as potências de dois é linear, você poderia dizer que o referido intervalo é o 0.1 / 64
décimo do intervalo entre as potências circundantes de dois (64 e 128), então você esperaria cerca de
(0.1 / 64) * 2**52
distinto double
s - que vem para 7036874417766.4004
... dar ou tirar um ou dois ;-).
2**64
valores duplos possíveis (já que é um tipo de 64 bits) e, aparentemente, uma proporção ENORME desses valores está entre os dois0..1
?Todo
double
valor cuja representação está entre0x0000000000000000
e0x3ff0000000000000
está no intervalo [0,0, 1,0]. São (2 ^ 62 - 2 ^ 52) valores distintos (mais ou menos um par, dependendo de você contar os pontos de extremidade).O intervalo [1.0, 2.0] corresponde às representações entre
0x3ff0000000000000
e0x400000000000000
; são 2 ^ 52 valores distintos.O intervalo [100,0, 101,0] corresponde às representações entre
0x4059000000000000
e0x4059400000000000
; são 2 ^ 46 valores distintos.Não há duplos entre 10 ^ 100 e 10 ^ 100 + 1 . Nenhum desses números é representável em precisão dupla, e não há duplos que caiam entre eles. Os dois números de precisão dupla mais próximos são:
e
fonte
Outros já explicaram que existem cerca de 2 ^ 62 duplos no intervalo [0,0, 1,0].
(Não é realmente surpreendente: há quase 2 ^ 64 duplos finitos distintos; desses, metade são positivos, e cerca de metade deles são <1,0.)
Mas você menciona geradores de números aleatórios: observe que um gerador de números aleatórios gerando números entre 0,0 e 1,0 não pode em geral produzir todos esses números; normalmente, ele produzirá apenas números na forma n / 2 ^ 53 com n um inteiro (consulte, por exemplo, a documentação Java para nextDouble ). Portanto, geralmente há apenas cerca de 2 ^ 53 (+/- 1, dependendo de quais terminais estão incluídos) valores possíveis para a
random()
saída. Isso significa que a maioria dos duplos em [0,0, 1,0] nunca será gerado.fonte
O artigo Nova matemática do Java, Parte 2: Números de ponto flutuante da IBM oferece o seguinte trecho de código para resolver isso (em flutuações, mas suspeito que funcione para duplos também):
Eles têm este comentário sobre isso:
fonte
float
, nãodouble
-float
s tem valor da fração de 23 bits', então2**23 -> 8388608
diferentes valores entre poderes adjacentes de dois (a parte 'inclusivo' significa, naturalmente, você tem que contar mais um, a próxima potência de dois).double
s têm frações de 52 bits!double
equivalente e pensei "Ei, vou responder minha própria pergunta em cerca de 5 minutos ..."double
potências adjacentes de dois levaria cerca de 52 dias (éprintln
claro que seria muito improvável que funcionasse tão rápido, não importa o quê, vamos supor que uma instrução desapareça ;-). Acho que é viável levar um ano ou menos em uma máquina poderosa, mas realista ;-).Veja o artigo da Wikipedia para mais informações.
fonte
1
é errado, porque o pouco escondida é sempre um - portanto,2^52
, não2^53
distintos valores (entre os poderes adjacentes de dois, um incluído e o próximo excluídos - não ! Entre 0,0 e 1,0).O duplo Java é um número binário64 IEEE 754.
Isso significa que precisamos considerar:
Isso basicamente significa que há um total de 2 ^ 62-2 ^ 52 + 1 de possíveis representações duplas que, de acordo com o padrão, estão entre 0 e 1. Observe que 2 ^ 52 + 1 é para remover os casos do não normalizado números.
Lembre-se de que se a mantissa for positiva, mas o expoente for negativo, o número é positivo, mas menor que 1 :-)
Para outros números é um pouco mais difícil porque os números inteiros da borda podem não ser representados de maneira precisa na representação IEEE 754, e porque existem outros bits usados no expoente para poder representar os números, portanto, quanto maior o número, menor os diferentes valores.
fonte