2017-07-13 2 views
0

Je donne les résultats suivants, en C++:Pourquoi le résultat de l'arithmétique double est-il faux?

double clsTime::dblSSM(INT16U uint16Hrs, INT16U uint16Mins, INT16U uint16Secs, INT16U uint16Hunds) { 
     double dblHrsAsSecs = (double)(uint16Hrs % 24) * 3600.0 
       ,dblMinsAsSecs = (double)(uint16Mins % 60) * 60.0 
       ,dblSecs  = (double)(uint16Secs % 60) 
       ,dblHundreths = (double)(uint16Hunds % 100)/100.0 
       ,dblSSM = dblHrsAsSecs + dblMinsAsSecs + dblSecs + dblHundreths;  
     return dblSSM;      
    } 

Lorsque vous appelez cette fonction avec:

dblResult = dblSSM(16, 56, 17, 13); 

Je peux voir dans le débogueur que les résultats des variables intermédiaires sont les suivantes:

dblHrsAsSecs = 57600 
    dblMinsAsSecs = 3360 
    dblSecs  = 17 
    dblHundreths = 0.13 

Cependant, lorsqu'il est combiné en dblSSM, le résultat est:

60977.1 

Ce que je veux est: 60977.13 qui est la bonne réponse, pourquoi le .03 étant abandonné et comment puis-je l'obtenir inclus?

Pour convertir en une chaîne pour la vérification:

void clsTime::ssmToString(double dblSSM, char* pszBuffer, char szFormat[]) { 
     INT8U uint8Hours, uint8Minutes, uint8Seconds, uint8Hundreths; 
     double dblDummy; 

     assert(pszBuffer != NULL); 
     long lngSSM = (long)dblSSM; 
     uint8Hours = (INT8U)(lngSSM/((long)mscuint16SecsInHour)); 
     uint8Minutes = (INT8U)((lngSSM % ((long)mscuint16SecsInHour))/
               (long)mscuint16SecsInMinute); 
     uint8Seconds = (INT8U)(lngSSM % (long)mscuint16SecsInMinute); 
     int8Hundreths = (INT8U)(modf(dblSSM, &dblDummy) * 100.0); 
     sprintf(pszBuffer, szFormat, uint8Hours, uint8Minutes 
         , uint8Seconds, uint8Hundreths); 
    } 

szFormat est un paramètre optionnel, la valeur par défaut transmis est:

"%02.2u:%02.2u:%02.2u.%02.2u" 
+1

Comment regardez-vous cette valeur? Avez-vous essayé d'imprimer la valeur par exemple avec plus de chiffres: https://stackoverflow.com/a/554134/8051589? –

+0

Toutes les valeurs sont affichées dans le débogueur, dans la fenêtre de surveillance. Si j'utilise la même valeur pour convertir en une chaîne, je peux voir que le résultat est aussi moins le .03 – SPlatten

+0

Est-ce que le débogueur peut afficher plus de chiffres ou juste celui que vous voyez? Essayez d'afficher plus de chiffres. Si ce n'est pas possible, utilisez std :: cout comme dans la réponse ci-dessus. –

Répondre

2

Je pense que ce n'est pas le résultat mais votre problème d'impression.
J'ai écrit ce programme:

#include <iostream> // cout 
#include <iomanip> // fixed, setprecision 

using namespace std; 

double dblSSM(__uint16_t uint16Hrs, __uint16_t uint16Mins, __uint16_t uint16Secs, __uint16_t uint16Hunds) { 
     double dblHrsAsSecs = (double)(uint16Hrs % 24) * 3600.0 
       ,dblMinsAsSecs = (double)(uint16Mins % 60) * 60.0 
       ,dblSecs  = (double)(uint16Secs % 60) 
       ,dblHundreths = (double)(uint16Hunds % 100)/100.0 
       ,dblSSM = dblHrsAsSecs + dblMinsAsSecs + dblSecs + dblHundreths;  
     return dblSSM;      
    } 

int main() { 

    cout << dblSSM(16, 56, 17, 13) << endl; // prints 60977.1 
    cout << fixed << setprecision(8)/*output 8 in the decimal part */ << dblSSM(16, 56, 17, 13) << endl; // prints 60977.13000000 

    return 0; 
} 

Je pense que cela fonctionne comme il se doit.
Si vous souhaitez imprimer en double, vous devez utiliser setprecision et fixed.

EDIT:

cout << fixed << setprecision(12) << (modf(dblSSM, &dblDummy) * 100.0); 

impressions 12.999999999738 si (__uint16_t)(modf(dblSSM, &dblDummy) * 100.0) donne 12. façon Hacky de résoudre ce problème est d'utiliser la fonction round, mais je vous suggère de ne pas utiliser doubles, sauf si vous avez vraiment.

+1

Le fait que cette réponse ait à la fois ['bits/stdC++. H'] (https://stackoverflow.com/questions/31816095/pourquoi- ne devrais- pas inclure -bits-stdc-h) et [' using namesapce std; '] (https://stackoverflow.com/questions/1452721/why-is-usus-namespace-std-considered-bad-practice) en fait une suggestion horrible pour tout futur lecteur. – StoryTeller

+1

DV rétractée. Pourtant, la directive d'utilisation me fait grincer des dents. – StoryTeller

+0

Mais ce n'est pas un problème d'affichage, pourquoi dblSSM est-il faux? Comment réparez-vous cela? – SPlatten