57 votes

Toutes les valeurs entières sont-elles parfaitement représentées sous forme de doubles?

Ma question est de savoir si toutes les valeurs entières sont la garantie d'avoir un parfait double représentation.

Considérons l'exemple de code suivant imprime "Même":

// Example program
#include <iostream>
#include <string>

int main()
{
  int a = 3;
  int b = 4;
  double d_a(a);
  double d_b(b);

  double int_sum = a + b;
  double d_sum = d_a + d_b;

  if (double(int_sum) == d_sum)
  {
      std::cout << "Same" << std::endl;
  }
}

Est-ce garanti pour être vrai pour n'importe quelle architecture, un compilateur, toutes les valeurs de a et b? Tout entier i convertis double, toujours être représentés en i.0000000000000 , et non pas, par exemple, i.000000000001?

Je l'ai essayé pour certains, d'autres chiffres et cela a toujours été vrai, mais a été incapable de trouver quelque chose quant à savoir si c'est un hasard ou par la conception.

Remarque: il est différent de cette question (en dehors de la langue) depuis que je suis en ajoutant les deux nombres entiers.

73voto

Beginner Points 2743

Avertissement (comme suggéré par Toby Speight): Bien que la norme IEEE 754 représentations sont assez fréquents, et une mise en œuvre est autorisé à utiliser toute autre représentation qui satisfait aux exigences de la langue.


Les doubles sont représentés sous la forme mantissa * 2^exponent, c'est à dire une partie des bits sont utilisés pour les non-partie entière du nombre double.

             bits        range                       precision
  float        32        1.5E-45   .. 3.4E38          7- 8 digits
  double       64        5.0E-324  .. 1.7E308        15-16 digits
  long double  80        1.9E-4951 .. 1.1E4932       19-20 digits

Schematic of IEEE 754 double type

La partie de la fraction peut également être utilisé pour représenter un nombre entier à l'aide d'un exposant qui supprime tous les chiffres après la virgule.

E. g. 2,9979 · 10^4 = 29979.

Depuis un commun int est généralement de 32 bits, vous pouvez représenter tous ints comme double, mais pour les entiers 64 bits bien sûr, ce n'est plus vrai. Pour être plus précis (comme LThode a fait remarquer dans un commentaire): la norme IEEE 754 double précision peut garantir ce jusqu'à 53 bits (52 bits de significande + l'implicite leader de 1 bit).

Réponse: oui pour la version 32 bits entiers, pas pour de 64 bits entiers.

(C'est correct pour le serveur/ordinateur de bureau à usage général CPU environnements, mais d'autres architectures peuvent se comporter différemment.)

Réponse pratique comme Malcom McLean: 64 bits double sont un suffisant de type entier pour presque tous les nombres entiers qui sont susceptibles de compter les choses dans la vraie vie.


Pour ce qui est empiriquement incliné, essayez ceci:

#include <iostream>
#include <limits>
using namespace std;

int main() {
    double test;
    volatile int test_int;
    for(int i=0; i< std::numeric_limits<int>::max(); i++) {
        test = i;
        test_int = test;

        // compare int with int:
        if (test_int != i)
            std::cout<<"found integer i="<<i<<", test="<<test<<std::endl;
    }
    return 0;
}

Le succès temps: 0.85 mémoire: 15240 signal:0


Subquestion: Concernant la question pour les fractions de différences. Est-il possible d'avoir un nombre entier qui correspond à un double qui est juste à côté de la valeur correcte par une fraction, mais qui reconvertit à la même entier en raison de l'arrondissement?

La réponse est non, parce que tout entier qui convertit en arrière et en avant à la même valeur, représente en fait la même valeur entière en double. Pour moi, le simplemost explication (suggéré par ilkkachu) pour cela est que l'utilisation de l'exposant 2^exponent la largeur doit toujours être une puissance de deux. Par conséquent, au-delà de la plus grande 52(+1 signe) bits entier, il n'y a jamais deux valeurs à une distance inférieure à 2, ce qui résout l'arrondissement problème de.

15voto

Pete Becker Points 27371

Non. Supposons que vous ayez un type entier 64 bits et un type virgule flottante 64 bits (ce qui est typique pour un double ). Il y a 2 ^ 64 valeurs possibles pour ce type entier et il y a 2 ^ 64 valeurs possibles pour ce type à virgule flottante. Cependant, certaines de ces valeurs à virgule flottante (en fait, la plupart) ne représentent pas des valeurs entières. Le type à virgule flottante peut donc représenter moins de valeurs entières que le type entier.

11voto

Corristo Points 2077

La réponse est non. Cela ne fonctionne que si ints sont en 32 bits, ce qui, si cela est vrai sur la plupart des plates-formes, n'est pas garanti par la norme.

Les deux nombres entiers peuvent partager le même double représentation.

Par exemple, cette

#include <iostream>
int main() {
    int64_t n = 2397083434877565865;
    if (static_cast<double>(n) == static_cast<double>(n - 1)) {
        std::cout << "n and (n-1) share the same double representation\n";
    }
}    

imprime

n et (n-1) partagent la même double représentation

I. e. les deux 2397083434877565865 et 2397083434877565864 se convertir à la même double.

Notez que j'ai utilisé int64_t ici pour garantir les entiers 64 bits, ce qui - en fonction de votre plate - forme peut également être ce qu' int .

4voto

Pablo H Points 354

Vous avez 2 questions différentes:

Sont toutes les valeurs entières parfaitement représenté en double?

Qui a déjà été répondu par d'autres personnes (TL;DR: il dépend de la précision de l' int et double).

Considérons l'exemple de code suivant imprime "Même": [...] Est-ce garanti pour être vrai pour n'importe quelle architecture, un compilateur, toutes les valeurs de a et b?

Votre code ajoute deux ints et puis convertit le résultat en double. La somme des ints va de dépassement de certaines valeurs, mais la somme des deux séparément convertis en doubles ne sera pas (généralement). Pour ces valeurs, les résultats seront différents.

2voto

Toby Speight Points 3930

La réponse courte est "peut-être". Le portable réponse est "partout".

Cela dépend vraiment de votre plate-forme, et, en particulier, sur

  • la taille et la représentation de l' double
  • la gamme de int

Pour les plates-formes à l'aide de la norme IEEE-754 double, il peut en être de même si int est de 53 bits ou plus petit. Pour les plates-formes où int est plus grand que double, c'est évidemment faux.

Vous pouvez être en mesure d'étudier les propriétés de votre exécution de l'hôte, à l'aide de std::numeric_limits et std::nextafter.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X