3 votes

De très grandes différences en utilisant le float et le double

#include <iostream>

using namespace std;

int main() {
    int steps=1000000000;
    float s = 0;
    for (int i=1;i<(steps+1);i++){
       s +=  (i/2.0) ; 
    }
    cout << s << endl;
}

Déclarer s como float : 9.0072e+15

Déclarer s como double 2.5e+17 (même résultat que l'implémentation en Julia)

Je comprends double a une double précision que float mais float devrait toujours gérer les nombres jusqu'à 10^38.

J'ai lu des sujets similaires où les résultats n'étaient pas les mêmes, mais dans ces cas-là les différences étaient très faibles, ici la différence est de 25x.

J'ajoute également qu'en utilisant long double au lieu de cela me donne le même résultat que double . Si la matière est la précision, je me serais attendu à avoir quelque chose d'un peu différent.

5voto

Hans Olsson Points 3454

Le problème est le manque de précision : https://en.wikipedia.org/wiki/Floating_point

Après 100 millions de nombres, vous ajoutez 1e8 à 1e16 (ou du moins des nombres de cette ampleur), mais les nombres à simple précision ne sont précis qu'à 7 chiffres - ce qui revient donc à ajouter 0 à 1e16 ; c'est pourquoi votre résultat est considérablement inférieur pour les flottants.

Préférez le double au flottant dans la plupart des cas.

0voto

user2079303 Points 4916

Vous n'avez pas mentionné quel type de nombres à virgule flottante vous utilisez, mais je vais supposer que vous utilisez IEEE 754, ou similaire.

Je comprends que le double a une double précision

Pour être plus précis avec la terminologie, le double utilise deux fois plus de bits. Ce n'est pas le double du nombre de valeurs représentables, c'est 4294967296 fois plus de valeurs représentables, malgré le nom "double précision".

mais float devrait toujours gérer les nombres jusqu'à 10^38.

Float peut gérer quelques nombres jusqu'à cette magnitude. Mais cela ne signifie pas que les valeurs des flottants dans cette plage sont précises. Par exemple, 3,4028235E+38 peut être représenté comme un flottant de simple précision. Quelle est, selon vous, la différence entre la valeur précédente représentable par float ? Est-ce l'epsilon de la machine ? Peut-être 0,1 ? Peut-être 1 ? Non. La différence est d'environ 2E+31.

Maintenant, vos chiffres ne sont pas tout à fait dans cette fourchette. Mais ils se situent en dehors de la plage continue des nombres entiers qui peuvent être représentés précisément par des flottants. La valeur la plus élevée de cette plage est 16777217, soit environ 1,7E+7, ce qui est bien inférieur à 2,5E+17. Ainsi, chaque addition au-delà de cette plage ajoute une erreur au résultat. Comme vous effectuez un milliard de calculs, ces erreurs s'additionnent.


Conclusions :

  • Comprenez que la précision simple est bien moins précise que la double précision.
  • Évitez les longues séquences de calculs où les erreurs de précision peuvent s'accumuler.

0voto

Ehsan Points 636

Problème de précision en virgule flottante ! Les nombres réels infinis ne peuvent pas être représentés par la mémoire finie d'un ordinateur. Les flottants, en général, ne sont que des approximations du nombre qu'ils sont censés représenter.

Pour plus de détails, veuillez consulter la documentation suivante : https://softwareengineering.stackexchange.com/questions/101163/what-causes-floating-point-rounding-errors

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