web-dev-qa-db-fra.com

Dois-je utiliser un double ou un flotteur?

Quels sont les avantages et les inconvénients d'utiliser l'un au lieu de l'autre en C++?

78
AraK

Si vous voulez connaître la vraie réponse, vous devriez lire Ce que tout informaticien devrait savoir sur l'arithmétique à virgule flottante .

En bref, bien que double permette une précision plus élevée dans sa représentation, pour certains calculs il produirait des erreurs plus importantes . Le "bon" choix est le suivant: utilisez autant de précision que nécessaire mais pas plus et choisissez le bon algorithme .

De nombreux compilateurs font de toute façon des calculs à virgule flottante étendus en mode "non strict" (c'est-à-dire qu'ils utilisent un type à virgule flottante plus large disponible dans le matériel, par exemple 80 bits et 128 bits flottants), cela doit également être pris en compte. En pratique, vous pouvez à peine voir aucune différence de vitesse - ils sont de toute façon natifs du matériel.

97
J-16 SDiZ

Sauf si vous avez une raison particulière de faire autrement, utilisez double.

Peut-être surprenant, c'est le double et non le flottant qui est le type à virgule flottante "normal" en C (et C++). Les fonctions mathématiques standard telles que sin et log prennent les doubles comme arguments et renvoient des doubles. Un littéral à virgule flottante normal, comme lorsque vous écrivez .14 dans votre programme, a le type double. Ne flotte pas.

Sur les ordinateurs modernes typiques, les doubles peuvent être aussi rapides que les flottants, voire plus rapides, donc les performances ne sont généralement pas un facteur à prendre en compte, même pour des calculs volumineux. (Et il faudrait que ce soit de gros calculs , ou les performances ne devraient même pas vous venir à l'esprit. Mon nouvel ordinateur de bureau i7 peut faire six milliards de multiplications de doubles en une seconde.)

35

Il est impossible de répondre à cette question car il n'y a pas de contexte à la question. Voici quelques éléments qui peuvent affecter le choix:

  1. Implémentation du compilateur de flotteurs, doubles et doubles longs. La norme C++ stipule:

    Il existe trois types de virgule flottante: float, double et long double. Le type double fournit au moins autant de précision que float, et le type long double fournit au moins autant de précision que double.

    Ainsi, les trois peuvent avoir la même taille en mémoire.

  2. Présence d'un FPU. Tous les processeurs n'ont pas de FPU et parfois les types à virgule flottante sont émulés et parfois les types à virgule flottante ne sont tout simplement pas pris en charge.

  3. Architecture FPU. Le FPU de l'IA32 est 80 bits en interne - les flottants 32 bits et 64 bits sont étendus à 80 bits en charge et réduits en magasin. Il y a aussi SIMD qui peut faire quatre flotteurs 32 bits ou deux flotteurs 64 bits en parallèle. L'utilisation de SIMD n'est pas définie dans la norme, elle nécessiterait donc un compilateur qui effectue une analyse plus complexe pour déterminer si SIMD peut être utilisé, ou nécessite l'utilisation de fonctions spéciales (bibliothèques ou intrinsèques). Le résultat du format interne 80 bits est que vous pouvez obtenir des résultats légèrement différents selon la fréquence à laquelle les données sont enregistrées dans RAM (donc perte de précision). Pour cette raison, les compilateurs n'optimisent pas code à virgule flottante particulièrement bien.

  4. Bande passante mémoire. Si un double nécessite plus de stockage qu'un flotteur, la lecture des données prendra plus de temps. Voilà la réponse naïve. Sur un IA32 moderne, tout dépend de la provenance des données. S'il est dans le cache L1, la charge est négligeable à condition que les données proviennent d'une seule ligne de cache. S'il s'étend sur plusieurs lignes de cache, il y a une petite surcharge. Si c'est de L2, ça prend un peu plus de temps, si c'est en RAM alors c'est encore plus long et enfin, si c'est sur disque c'est un temps énorme. Donc le choix de float ou double est moins important que la façon dont les données sont utilisées. Si vous voulez faire un petit calcul sur un grand nombre de données séquentielles, un petit type de données est préférable. Faire beaucoup de calculs sur un petit ensemble de données vous permettrait d'utiliser des types de données plus gros avec n'importe quel Si vous accédez aux données de manière très aléatoire, le choix de la taille des données est sans importance - les données sont chargées dans les pages/lignes de cache. Ainsi, même si vous ne voulez qu'un octet de la RAM, vous pouvez obtenir 32 octets transférés (c'est très dépendante de l'architecture du système). En plus de tout cela, le CPU/FPU pourrait être super-scalaire (alias pipelined). Ainsi, même si une charge peut prendre plusieurs cycles, le CPU/FPU pourrait être occupé à faire autre chose (une multiplication par exemple) qui cache le temps de chargement à un degré.

  5. La norme n'applique aucun format particulier pour les valeurs à virgule flottante.

Si vous avez une spécification, cela vous guidera vers le choix optimal. Sinon, c'est à l'expérience de savoir quoi utiliser.

27
Skizz

Double est plus précis mais est codé sur 8 octets. float n'est que de 4 octets, donc moins d'espace et moins de précision.

Vous devez être très prudent si vous avez double et flottant dans votre application. J'ai eu un bug à cause de ça dans le passé. Une partie du code utilisait float tandis que le reste du code utilisait double. Copier double pour flotter puis flotter pour doubler peut entraîner une erreur de précision qui peut avoir un impact important. Dans mon cas, c'était une usine de produits chimiques ... j'espère que cela n'a pas eu de conséquences dramatiques :)

Je pense que c'est à cause de ce genre de bug que la fusée Ariane 6 a explosé il y a quelques années !!!

Réfléchissez bien au type à utiliser pour une variable

13
luc

Personnellement, je vais doubler tout le temps jusqu'à ce que je vois des goulots d'étranglement. Ensuite, je pense à bouger pour flotter ou à optimiser une autre partie

6
Eric

Cela dépend de la façon dont le compilateur implémente le double. Il est légal que double et float soient du même type (et c'est sur certains systèmes).

Cela dit, s’ils sont effectivement différents, le principal problème est la précision. Un double a une précision beaucoup plus élevée en raison de sa différence de taille. Si les nombres que vous utilisez dépassent généralement la valeur d'un flotteur, utilisez un double.

Plusieurs autres personnes ont mentionné des problèmes de performance. Ce serait exactement le dernier sur ma liste de considérations. L'exactitude devrait être votre considération n ° 1.

4
JaredPar

tilisez la précision requise pour obtenir les résultats appropriés . Si vous constatez ensuite que votre code ne fonctionne pas aussi bien que vous le souhaitez (vous avez utilisé le profilage correctement?), Jetez un œil à:

3
user7116

Je pense que quelles que soient les différences (qui, comme tout le monde le fait remarquer, les flotteurs prennent moins de place et sont en général plus rapides) ... est-ce que quelqu'un souffre de problèmes de performances en utilisant le double? Je dis utiliser double ... et si plus tard vous décidez "wow, c'est vraiment lent" ... trouvez votre goulot d'étranglement de performance (ce qui n'est probablement pas le fait que vous ayez utilisé double). ALORS, si c'est encore trop lent pour vous, voyez où vous pouvez sacrifier une certaine précision et utiliser float.

2
Tom

La principale différence entre float et double est la précision. Wikipedia a plus d'informations sur Simple précision (float) et Double précision .

1
Michaël Larouche

Cela dépend fortement du processeur, les compromis les plus évidents se situent entre la précision et la mémoire. Avec des Go de RAM, la mémoire n'est pas vraiment un problème, il est donc généralement préférable d'utiliser doubles.

Quant aux performances, elles dépendent fortement du CPU. floats obtiendra généralement de meilleures performances que doubles sur une machine 32 bits. Sur 64 bits, les double sont parfois plus rapides, car il s'agit (généralement) de la taille native. Pourtant, ce qui importera beaucoup plus que votre choix de types de données est de savoir si vous pouvez ou non profiter des instructions SIMD sur votre processeur.

1
Zifre

double a une précision plus élevée, tandis que les flottants prennent moins de mémoire et sont plus rapides. En général, vous devez utiliser float sauf si vous avez un cas où il n'est pas suffisamment précis.

0
Tal Pressman