Les Java double
sont au format IEEE-754 , ils ont donc une fraction de 52 bits; entre deux puissances adjacentes quelconques de deux (dont une incluse et excluant la suivante), il y aura donc 2 à la 52e puissance double
s différentes (c'est-à-dire 4503599627370496 d'entre elles). Par exemple, c'est le nombre de double
s distincts entre 0,5 inclus et 1,0 exclus, et exactement ce nombre se situe également entre 1,0 inclus et 2,0 exclus, et ainsi de suite.
Compter doubles
entre 0,0 et 1,0 est plus difficile que de le faire entre des puissances de deux, car il y a de nombreuses puissances de deux comprises dans cette gamme, et, aussi, on entre dans les questions épineuses des nombres dénormalisés. 10 des 11 bits des exposants couvrent la plage en question, donc, y compris les nombres dénormalisés (et je pense que quelques types de NaN
), vous auriez 1024 fois le double
s entre les puissances de deux - pas plus que le 2**62
total de toute façon . Hors dénormalisé & c, je crois que le décompte serait de 1023 fois 2**52
.
Pour une plage arbitraire comme "100 à 100,1", c'est encore plus difficile car la limite supérieure ne peut pas être représentée exactement comme un double
(n'étant pas un multiple exact d'une puissance de deux). En guise d'approximation pratique, puisque la progression entre les puissances de deux est linéaire, vous pourriez dire que ladite plage est 0.1 / 64
la plage entre les puissances environnantes de deux (64 et 128), donc vous vous attendez à environ
(0.1 / 64) * 2**52
double
s distincts - ce qui revient à 7036874417766.4004
... donner ou prendre un ou deux ;-).
2**64
valeurs doubles possibles (car c'est un type 64 bits), et apparemment une ÉNORME proportion de ces valeurs se situe entre0..1
?Toute
double
valeur dont la représentation est comprise entre0x0000000000000000
et0x3ff0000000000000
se situe dans l'intervalle [0.0, 1.0]. C'est (2 ^ 62 - 2 ^ 52) valeurs distinctes (plus ou moins un couple selon que vous comptez les points finaux).L'intervalle [1.0, 2.0] correspond aux représentations entre
0x3ff0000000000000
et0x400000000000000
; c'est 2 ^ 52 valeurs distinctes.L'intervalle [100,0, 101,0] correspond aux représentations entre
0x4059000000000000
et0x4059400000000000
; c'est 2 ^ 46 valeurs distinctes.Il n'y a pas de doubles entre 10 ^ 100 et 10 ^ 100 + 1 . Aucun de ces nombres n'est représentable en double précision, et il n'y a pas de doubles entre eux. Les deux nombres à double précision les plus proches sont:
et
la source
D'autres ont déjà expliqué qu'il y a environ 2 ^ 62 doubles dans l'intervalle [0,0, 1,0].
(Pas vraiment surprenant: il y a près de 2 ^ 64 doubles finis distincts, de ceux -ci , la moitié sont positifs, et à peu près la moitié de ceux qui sont <1,0.)
Mais vous évoquez des générateurs de nombres aléatoires: notez qu'un générateur de nombres aléatoires générant des nombres compris entre 0,0 et 1,0 ne peut en général pas produire tous ces nombres; typiquement, il ne produira que des nombres de la forme n / 2 ^ 53 avec n un entier (voir par exemple la documentation Java pour nextDouble ). Il n'y a donc généralement qu'environ 2 ^ 53 (+/- 1, selon les points de terminaison inclus) des valeurs possibles pour la
random()
sortie. Cela signifie que la plupart des doubles dans [0.0, 1.0] ne seront jamais générés.la source
L'article Les nouvelles mathématiques de Java, Partie 2: Nombres à virgule flottante d'IBM propose l'extrait de code suivant pour résoudre ce problème (en flottants, mais je suppose que cela fonctionne également pour les doubles):
Ils ont ce commentaire à ce sujet:
la source
float
, pasdouble
-float
s ont 23 bits de fraction, donc2**23 -> 8388608
des valeurs différentes entre les puissances adjacentes de deux (la partie "inclusive" signifie bien sûr que vous devez en compter une de plus, la puissance suivante de deux).double
s ont des fractions de 52 bits!double
équivalent et je me suis dit "Hé, je vais répondre à ma propre question dans environ 5 minutes ..."double
entre des puissances adjacentes de deux prendrait environ 52 jours (println
bien sûr, il serait très peu probable qu'il fonctionne aussi vite quoi qu'il arrive, donc Supposons qu'une déclaration disparaisse ;-). Je pense qu'il est possible de prendre un an ou moins sur une machine puissante mais réaliste ;-).Voir l' article wikipedia pour plus d'informations.
la source
1
est faux parce que le peu caché est toujours un - donc2^52
, pas2^53
distinctes des valeurs (entre les puissances adjacentes de deux, celui qui est inclus et exclus le prochain - pas ! Entre 0,0 et 1,0).Le double Java est un nombre binaire64 IEEE 754.
Cela signifie que nous devons considérer:
Cela signifie essentiellement qu'il y a un total de 2 ^ 62-2 ^ 52 + 1 de doubles représentations possibles qui, selon la norme, sont comprises entre 0 et 1. Notez que 2 ^ 52 + 1 consiste à supprimer les cas des non normalisés Nombres.
Rappelez-vous que si la mantisse est positive mais que l'exposant est négatif, le nombre est positif mais inférieur à 1 :-)
Pour les autres nombres, c'est un peu plus difficile car les nombres entiers de bord peuvent ne pas être représentables de manière précise dans la représentation IEEE 754, et parce qu'il y a d'autres bits utilisés dans l'exposant pour pouvoir représenter les nombres, donc plus le nombre est grand, plus le nombre est bas. les différentes valeurs.
la source