Dois-je utiliser double ou float?

89

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

AraK
la source
Quelqu'un a-t-il essayé de créer un tableau de flottants et un tableau de doubles et voir s'il y a effectivement 4 octets entre les membres sur les flottants et 8 octets entre les membres sur les doubles? Il est possible qu'un compilateur / ordinateur 64 bits réserve toujours 8 octets par membre pour les flottants même s'ils n'en ont pas besoin de beaucoup.
user3015682

Réponses:

104

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 qu'elle doublepermette une plus grande précision dans sa représentation, pour certains calculs, elle produirait des erreurs plus importantes . Le "bon" choix est: utilisez autant de précision que vous en avez besoin 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 ne pouvez guère voir de différence de vitesse - ils sont de toute façon natifs du matériel.

J-16 SDiZ
la source
10
Oui. Avec les processeurs modernes qui prélèvent des morceaux de mémoire de plus en plus grands, des unités de traitement numérique parallèles et des architectures en pipeline, le problème de la vitesse n'est vraiment pas un problème. Si vous avez affaire à d'énormes quantités de nombres, peut-être que la différence de taille entre un flottant de 4 octets et un double de 8 octets pourrait faire une différence dans l'empreinte mémoire.
lavinio
5
Eh bien, SSE (ou toute unité à virgule flottante verteor) sera capable de traiter deux fois le nombre de flops en simple précision par rapport à la double précision. Si vous ne faites que x87 (ou tout autre scalaire) en virgule flottante, cela n'aura probablement pas d'importance.
Greg Rogers
1
@Greg Rogers: les compilateurs ne sont pas si intelligents en ce moment. À moins que vous n'écriviez un assemblage brut, il n'y a pas de grande différence. Et oui, cela peut changer à mesure que le compilateur évolue.
J-16 SDiZ
Une note supplémentaire: si vous n'avez absolument aucune idée de ce à quoi ressemblent les données (ou si vous n'avez simplement aucune idée de tous les calculs dans les liens), utilisez simplement double- c'est plus sûr dans la plupart des cas.
J-16 SDiZ
2
Ce papier n'est pas court.
jokoon
44

Sauf si vous avez une raison spécifique de faire autrement, utilisez double.

Peut-être étonnamment, c'est double et non float qui est le type à virgule flottante "normal" en C (et C ++). Les fonctions mathématiques standard telles que sin et log take double comme arguments et retournent des doubles. Un littéral normal à virgule flottante, comme lorsque vous écrivez 3.14 dans votre programme, a le type double. Pas flotter.

Sur les ordinateurs modernes typiques, les doubles peuvent être aussi rapides que les flottants, voire même plus rapides, de sorte que les performances ne sont généralement pas un facteur à prendre en compte, même pour les gros calculs. (Et ce devrait être de gros calculs, ou les performances ne devraient même pas entrer dans votre esprit. Mon nouvel ordinateur de bureau i7 peut faire six milliards de multiplications de doubles en une seconde.)

Thomas Padron-McCarthy
la source
26

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 longs doubles. Le standard C ++ déclare:

    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'une 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 de 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, il faudrait donc un compilateur qui effectue des analyses plus complexes 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 en fonction de la fréquence à laquelle les données sont enregistrées dans la RAM (ainsi, une perte de précision). Pour cette raison, les compilateurs n'optimisent pas particulièrement bien le code en virgule flottante.

  4. Bande passante mémoire. Si un double nécessite plus de stockage qu'un flottant, la lecture des données prendra plus de temps. C'est la réponse naïve. Sur un IA32 moderne, tout dépend de la provenance des données. Si c'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 plus d'une ligne de cache, il y a une petite surcharge. Si c'est à partir de L2, cela prend un peu plus de temps, si c'est en RAM, c'est encore plus long et enfin, si c'est sur disque, c'est un temps énorme. Le choix du flottant ou du double est donc moins important que la façon dont les données sont utilisées. Si vous souhaitez effectuer un petit calcul sur de nombreuses 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 volumineux avec un effet significatif. Si vous' si vous accédez aux données de manière très aléatoire, le choix de la taille des données n'a pas d'importance - les données sont chargées dans les pages / lignes de cache. Donc, même si vous ne voulez qu'un octet de la RAM, vous pourriez obtenir 32 octets transférés (cela dépend beaucoup de l'architecture du système). En plus de tout cela, le CPU / FPU pourrait être super-scalaire (aka pipelined). Ainsi, même si une charge peut prendre plusieurs cycles, le CPU / FPU peut être occupé à faire autre chose (une multiplication par exemple) qui masque le temps de chargement dans une certaine mesure.

  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 une question d'expérience quant à ce qu'il faut utiliser.

Skizz
la source
16

Le double est plus précis mais est codé sur 8 octets. float ne fait que 4 octets, donc moins de place et moins de précision.

Vous devez être très prudent si vous avez double et float dans votre application. J'ai eu un bug à cause de cela dans le passé. Une partie du code utilisait float tandis que le reste du code utilisait double. Copier le 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 chimique ... 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

luc
la source
3
Notez que 4/8 octets pour float / double n'est même pas garanti, cela dépendra de la plateforme. Il pourrait même être du même type ...
sleske
2
Le code d' Ariane 5 a tenté de convertir une virgule flottante 64 bits, dont la valeur était supérieure à 32 767, en un entier signé 16 bits. Cela a généré une exception de débordement qui a amené la fusée à lancer sa séquence d'autodestruction. Le code en question était du code réutilisé à partir d'une fusée plus ancienne et plus petite.
cmwt
5

Personnellement, je double tout le temps jusqu'à ce que je vois des goulots d'étranglement. Ensuite, j'envisage de passer à flotter ou d'optimiser une autre partie

Eric
la source
4

Cela dépend de la façon dont le compilateur implémente double. Il est légal que double et float soient du même type (et c'est le cas 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 flottant, utilisez un double.

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

JaredPar
la source
2

Je pense que quelles que soient les différences (qui, comme tout le monde le souligne, les flotteurs prennent moins de place et sont en général plus rapides) ... est-ce que quelqu'un a déjà souffert de problèmes de performance 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 avez utilisé le double). ALORS, si c'est encore trop lent pour vous, voyez où vous pouvez sacrifier un peu de précision et utiliser le flotteur.

À M
la source
1

Cela dépend fortement du processeur, les compromis les plus évidents sont entre précision et 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 processeur. floats obtiendront généralement de meilleures performances que doubles sur une machine 32 bits. Sur 64 bits, les doubles sont parfois plus rapides, car il s'agit (généralement) de la taille native. Néanmoins, ce qui importera beaucoup plus que votre choix de types de données, c'est de savoir si vous pouvez ou non profiter des instructions SIMD sur votre processeur.

Zifre
la source
0

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 devriez utiliser float sauf si vous avez un cas où il n'est pas assez précis.

Tal Pressman
la source
5
Sur les ordinateurs modernes typiques, le double est aussi rapide que le flottement.
Thomas Padron-McCarthy