IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C++ Discussion :

Erreur floating point exception


Sujet :

C++

  1. #1
    Membre éclairé
    Avatar de Wachter
    Homme Profil pro
    Développeur
    Inscrit en
    Octobre 2008
    Messages
    404
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Octobre 2008
    Messages : 404
    Points : 734
    Points
    734
    Par défaut Erreur floating point exception
    Bonjour,

    J'ai écrit un code qui affiche un nombre entier N sous la forme : N = a1 x 1! + a2 x 2! + ... + ap x p! avec a1 + ... + ap minimal.

    Exemple 1
    Entrée : N = 52
    Sortie : p = 4 ; les coefficients sont : 0, 2, 0, 2

    Exemple 2
    Entrée : N = 120
    Sortie : p = 5 ; les coefficients sont : 0, 0, 0, 0, 1

    J'obtiens l'erreur Floating Point Exception sur un serveur d'évaluation pour un entier donné que j'ignore (N <= 500 millions). Pourtant, j'ai évité une division par 0 (ou un modulo).

    Pour N = 479 000 000, j'ai p = 11 et les coefficients : 0, 1, 1, 3, 4, 4, 7, 8, 9, 10, 11
    Pour N = 480 000 000, il affiche p = 12 puis se plante !
    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    #include <iostream>
    #include <stack>
    #include <cstdio>
    using namespace std;
    stack<int> coef;
     
     
    int main()
    {
       int nb;
       scanf("%d", &nb);
     
       int fact = 1;
       int rang = 1;
       while (fact <= nb)
       {
           rang = rang + 1;
           fact = fact * rang;
       }
       fact = fact / rang;
       rang = rang - 1;
     
       printf("%d\n", rang);
       coef.push(nb / fact);
     
       while (rang >= 2)
       {
           nb = nb % fact;
           fact = fact / rang;
           rang = rang - 1;
           coef.push(nb / fact);
       }
     
       while(!coef.empty())
       {
           printf("%d ", coef.top());
           coef.pop();
       }
    }
    Merci pour votre aide !
    Code parrain certification Voltaire : NTMPH759

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Y'a fort à parier que fact = fact / rang; vaut 0 à un moment donné.
    Utilise un vrai debugger et tu le sauras assez vite.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Membre émérite
    Avatar de imperio
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2010
    Messages
    852
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 852
    Points : 2 298
    Points
    2 298
    Par défaut
    De manière générale, j'ai toujours tendance à me méfier des divisions (et des modulos aussi). Si je suis certain que le diviseur ne sera jamais 0, je n'y mets pas de condition, sinon :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    float nombre, diviseur;
     
    nombre = (diviseur != 0 ? nombre / diviseur : 0);

  4. #4
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    13! = 6227020800 > INT_MAX après quoi on ne peut plus compter sur rien.

    @imperio, pourquoi utiliser des float ici? (en général, il vaut mieux ne pas utiliser les flottants. Quand il le faut, les doubles sont le choix normal, les floats ayant une précision faible ne sont à utiliser qu'après avoir montré qu'ils conviennent)
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  5. #5
    Membre émérite
    Avatar de imperio
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2010
    Messages
    852
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 852
    Points : 2 298
    Points
    2 298
    Par défaut
    @Jean-Marc.Bourguet: Pas de raison particulière. Ça aurait tout aussi bien pu être un char qu'un unsigned long double. Je donnais juste un exemple.

    Concernant la précision faible des floats, je ne suis pas sûr de te suivre. La majorité des codes de bibliothèques mathématiques que j'ai vu utilisaient des floats et non des doubles. Si c'était vraiment si faible que ça, pourquoi ne pas utiliser des doubles dans ce cas ?

  6. #6
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 074
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 074
    Points : 12 120
    Points
    12 120
    Par défaut
    Pour la vitesse.

  7. #7
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par imperio Voir le message
    @Jean-Marc.Bourguet: Pas de raison particulière. Ça aurait tout aussi bien pu être un char qu'un unsigned long double. Je donnais juste un exemple.

    Concernant la précision faible des floats, je ne suis pas sûr de te suivre. La majorité des codes de bibliothèques mathématiques que j'ai vu utilisaient des floats et non des doubles. Si c'était vraiment si faible que ça, pourquoi ne pas utiliser des doubles dans ce cas ?
    La totalité des bibliothèques mathématiques que j'ai vu étaient soit disponible en float, double, voire extended et quad, ou pour celles en C++ template sur le type flottant. Et faites par des gens capables de faire l'analyse de propagation d'erreur. Un float a 24 bits de précision. Un calcul naïf perd facilement un bit par niveau. Plus si la malchance s'en mêle.

    Citation Envoyé par bacelar Voir le message
    Pour la vitesse.
    Ça reste à mesurer.

    En fait, tout dépend des calculs, si c'est du calcul relativement simple, homogène à faire sur des masses de données, float a du sens, en particulier si c'est vectorisable ou que le facteur limitant est la bande passante. Sinon je maintiens: float n'est pas le type à utiliser par défaut.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  8. #8
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 074
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 074
    Points : 12 120
    Points
    12 120
    Par défaut
    Attention, je suis à 200% derrière Jean-Marc.Bourguet sur le faite qu'on doit utiliser double par défaut.
    S'il y a des float dans des bibliothèques numériques c'est que cela peut avoir un avantage de vitesse (calcul parallélisable sur architecture SIMD, etc.), je ne chercherai pas des poux dans les cheveux dans la tête des auteurs de bibliothèques qui ont largement un niveau supérieur à la moyen en ce qui concerne l'analyse numérique et l'optimisation algébrique.

  9. #9
    Membre éclairé
    Avatar de Wachter
    Homme Profil pro
    Développeur
    Inscrit en
    Octobre 2008
    Messages
    404
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Octobre 2008
    Messages : 404
    Points : 734
    Points
    734
    Par défaut
    Je vous remercie pour vos interventions.

    Cependant, ce que je ne comprends pas c'est que la condition rang >= 2 devrait logiquement empêcher une éventuelle division par zéro dans l'instruction fact = fact / rang;.

    Pour ce qui est d'un éventuel dépassement de la limite du type int, on est certain de calculer au plus 12! (N <= 500 000 000).
    Code parrain certification Voltaire : NTMPH759

  10. #10
    Membre chevronné Avatar de Astraya
    Homme Profil pro
    Consommateur de café
    Inscrit en
    Mai 2007
    Messages
    1 043
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Consommateur de café
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 043
    Points : 2 234
    Points
    2 234
    Par défaut
    Citation Envoyé par bacelar Voir le message
    Pour la vitesse.
    Quoi? un double est plus rapide qu'un float?

    Un petit récap de comment fonctionne la mémoire et la taille des bus...
    Si le bus mémoire est de 32 bits soit 4 octets donc il lit des lignes de 4 octets dans la mémoire, donc si le programme demande de lire un float (4 octets aligné sur 32/64/128 bits ), il n'y à qu'un seul accès à la mémoire. Si le programme demande de lire un double ( 8 octets aligné sur 32/64/128 bits ) il fait automatiquement 2 appel mémoire donc il y a deux utilisation du bus non pas 1 pour un float. Donc non le double n'est pas plus rapide qu'un float quand on parle de la mémoire.
    Si le bus est de 64 bits (DDR, DDR2, or DDR3) alors c'est idem pour float et double... sauf! au cas ou tu lit 2 float contiguë en mémoire aligné... tu n'auras que une lecture de faite.

    Ça va également dépendre de si tu compile en 32bits ou 64bits.

    Tu auras une différence en fonction de ton matériel coté calcul sur float/double. Tout vas dépendre du FPU de ton processeur. Mais généralement aujourd'hui le float sera émulé en double et donc le float sera plus long que de travailler directement avec un double et encore... ici encore cela va dépendre de ton FPU ici aussi.

    Donc:

    Le float ne sera pas forcement toujours plus rapide qu'un double et inversement et ce avec le même code. Tout dépend de la machine...

    Il faut toujours prendre un float car 4 octets car sera toujours lu en 1 seul accès mémoire peut importe ta machine ( tout du moins si elle à un bus de 32 bits minimum) sauf mettre double pour les cas ou MAX_FLOAT est insuffisant, mais l'algorithme sera donc plus lent car plus d'accès via le bus mémoire.

    Pour le coté historique, la mémoire évolue beaucoup moins rapidement que le processeur donc si tu veux optimiser, 90% du temps tu le fais coté mémoire.

    Voila pourquoi les librairies travaille en float et également les moteurs de jeu vidéo, et peuvent fournir une surcharge en double au besoin. Et coté précision, c'est très rare d'avoir besoin de plus que float.
    Homer J. Simpson


  11. #11
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par Wachter Voir le message
    Pour ce qui est d'un éventuel dépassement de la limite du type int, on est certain de calculer au plus 12! (N <= 500 000 000).
    Si tu affiches p=12, tu as calcule 13! dans ton programme.

    Citation Envoyé par Astraya Voir le message
    Quoi? un double est plus rapide qu'un float?
    Ou ca? J'ai ecrit qu'il fallait mesurer en reponse a une affirmation qu'utiliser float etait bon pour les perfs, donc sous-entendant que float n'etait pas necessairement plus rapide que double, mais certainement pas que les doubles sont plus rapides que les float.

    Un petit récap
    Acces memoire:

    1/ si on n'est pas en cache, inutile de parler de perf de calcul, c'est un probleme d'optimisation de bande passante (et j'ai explicitement dit que les cas ou la BP est un facteur limitant sont les cas ou il faut envisager float, apres avoir confirme que la precision est suffisante)
    2/ tout les acces en lecture a la memoire principale transferent des lignes completes de cache
    3/ si tes donnees ne sont pas alignees de sorte qu'elles sont completement dans une ligne de cache, a nouveau inutile de parler de perf de calcul
    4/ si tes donnees sont completement dans la ligne de cache, leur taille n'a pas d'importance.

    Sur l'aspect CPU (que dissocier qu'un FPU de nos jours n'a plus guere de sens). Les CPU etant pipeline, superscalaire, a execution dans le desordre, ils peuvent avoir plus d'une centaine d'instruction en cours d'execution. Le temps d'execution d'une instruction n'a plus de sens, il faut regarder un groupe et voir comment le processeur gere. Les interdependances ont de bonnes chances de masquer les differences entre float et double, sauf quand tout est concu pour (en gros les cas vectorisable, qu'on utilise ou non des instructions pour).

    Le float ne sera pas forcement toujours plus rapide qu'un double et inversement et ce avec le même code. Tout dépend de la machine...
    Et nous sommes d'accord sur la conclusion.

    Il faut toujours prendre un float car 4 octets car sera toujours lu en 1 seul accès mémoire peut importe ta machine ( tout du moins si elle à un bus de 32 bits minimum) sauf mettre double pour les cas ou MAX_FLOAT est insuffisant, mais l'algorithme sera donc plus lent car plus d'accès via le bus mémoire.
    Le probleme n'est pas souvent MAX_FLOAT, c'est le nombre de bits de la "mantisse" qui n'est que de 24 pour les floats. C'est 6 chiffres decimaux et bien souvent trop peu pour garder une precision suffisante quand on enchaine des calculs.

    Voila pourquoi les librairies travaille en float et également les moteurs de jeu vidéo, et peuvent fournir une surcharge en double au besoin. Et coté précision, c'est très rare d'avoir besoin de plus que float.
    Les librairies de calculs sont tres souvent disponibles en float, double, extended et parfois quad, celles en C++ sont souvent templatees.

    Pour ce qui concerne les jeux videos, l'affichage a besoin de 13/14 bits de precision finale, que les 24 de float suffisent souvent ne m'etonnerait pas trop. Mais c'est un domaine atypique de ce point de vue, je reste sur ma position: double est le type flottant a utiliser par defaut
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  12. #12
    Membre éclairé
    Avatar de Wachter
    Homme Profil pro
    Développeur
    Inscrit en
    Octobre 2008
    Messages
    404
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Octobre 2008
    Messages : 404
    Points : 734
    Points
    734
    Par défaut
    Si tu affiches p=12, tu as calcule 13! dans ton programme.
    Oups... Tu as raison. Même l'utilisation des long int ne résoudra pas le problème.
    Code parrain certification Voltaire : NTMPH759

  13. #13
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par Wachter Voir le message
    Oups... Tu as raison. Même l'utilisation des long int ne résoudra pas le problème.
    long long, ou changer la condition en (fact < nb/(rang+1).
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Floating point exception sous linux
    Par doommick31 dans le forum C++
    Réponses: 4
    Dernier message: 20/12/2012, 18h22
  2. [runtime exception] Floating point exception
    Par xion.luhnis dans le forum x86 32-bits / 64-bits
    Réponses: 2
    Dernier message: 17/09/2010, 04h57
  3. Floating Point Exception
    Par étoile de mer dans le forum Débuter
    Réponses: 3
    Dernier message: 28/10/2009, 17h09
  4. Réponses: 1
    Dernier message: 06/05/2009, 16h36
  5. Floating point exception dans dlopen()
    Par Invité dans le forum C++
    Réponses: 0
    Dernier message: 10/06/2008, 09h56

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo