Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
2670 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  [C] Problème très con sur une fonction apparemment super simple

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[C] Problème très con sur une fonction apparemment super simple

n°234146
sielfried
Posté le 24-10-2002 à 22:02:47  profilanswer
 

Salut à tous,  
 
Voici la fonction en question :
 

Code :
  1. int hhmmToMin(float hhmm)
  2. {
  3. int hh = hhmm;
  4. int mm = (hhmm - hh) * 100;
  5. return (hh*60 + mm);
  6. }


 
Son objectif : en gros l'utilisateur tape une heure sous forme de valeur float (genre 12.30 pour 12h30) et la fonction doit transformer ça en nombre de minutes. Vraiment basique quoi a priori.
 
J'ai décomposé en deux variables pour que ce soit plus clair, même si j'aurais pu inclure la seconde dans le return (voire même les deux premières, avec des cast). Mais là n'est pas le problème.
 
Si je tape 1.55, la fonction me renvoie 114 (1*60 + 54) et non 115 (1*60 + 55). Avec d'autres valeurs des fois ça fonctionne, des fois non.
 
Pour hh pas de problèmes, elle prend la partie entière de 1.55, soit 1, par transtypage implicite.
 
C'est pour mm que ça pose problème : d'après le débuggeur la parenthèse donne bien le résultat escompté (0.550000), la multiplication par 100 aussi (55.0000). Mais lors de la conversion en int pour stocker le tout dans mm... cela donne 54, pas 55.
 
Ce qu'il y a de marrant, c'est que si je décompose la fonction comme cela :
 

Code :
  1. int hhmmToMin(float hhmm)
  2. {
  3. int hh = hhmm;
  4. float mmtemp = (hhmm - hh) * 100;
  5. int mm = mmtemp;
  6. return (hh*60 + mm);
  7. }


 
... et que je mets un breakpoint sur l'avant-dernière ligne, voici ce que me dit le débugger (si je lui demande) :
 
* mmtemp = 55.0000
* (int)mmtemp = 54
* (int)55.0000 = 55
 
 :heink:  
 
J'ai essayé de changer de types en mettant des double à la place des float, j'ai aussi essayé de transtyper tout explicitement, rien n'y fait, j'obtiens toujours 114.
 
C'est sûrement tout con, si qqun peut m'expliquer je suis preneur. Chui pas newbie en C/C++ mais ça fait un mmt que j'en avais pas refait, j'ai dû oublier qq trucs importants :o
 
D'ailleurs y'a p-e plus simple pour faire ce que la fonction fait...
 
Merci d'avance.


Message édité par sielfried le 24-10-2002 à 22:10:09

---------------
StarCraft Professional Gaming Database | [Ze Topic] Starcraft/BroodWar
mood
Publicité
Posté le 24-10-2002 à 22:02:47  profilanswer
 

n°234171
bjone
Insert booze to continue
Posté le 24-10-2002 à 23:21:11  profilanswer
 

soit j'ai de la merde dans les yeux, soit ton code y reviens à ça:
 

Code :
  1. int hhmmToMin(float hhmm)
  2. {
  3. return ( hhmm*60 );
  4. }

n°234172
bjone
Insert booze to continue
Posté le 24-10-2002 à 23:23:00  profilanswer
 

(hhmm - hh)
=> 0 vu que hh == hhmm
 
int mm = (hhmm - hh) * 100;  
=> 0
 
return (hh*60 + mm);  
=> return (hhmm*60 + 0)

n°234173
bjone
Insert booze to continue
Posté le 24-10-2002 à 23:23:49  profilanswer
 

a non oups !!!!!
 
autant pour moi j'ai dit une connerie !!! :D (fatigué vais faire un nolf2)
 
tu peux essayer d'ajouter un +0.5 pour compenser les erreurs d'arrondi par défaut...
 
mmmm.....  
 
et ça ?
 
float mmtemp = (hhmm - (float)hh) * 100;
 
histoire d'être sûr qu'il reste en virgule flottante tout le long ?


Message édité par bjone le 24-10-2002 à 23:28:37
n°234178
VisualC++
J'va y penser ...
Posté le 24-10-2002 à 23:40:23  profilanswer
 

ca ca marche mais galere entre float et double et int pour la precision (d ou le pb de 30.0 qui passe a 29)
 

Code :
  1. int g_fniHhmmToMin(double dHhmm)
  2. {
  3. char buffer[50];
  4. double dHh = floor(dHhmm);
  5. double dTmp = (dHhmm - dHh) * 100.0;
  6. _gcvt(dTmp, 10, buffer);
  7. int iMm = atoi(buffer);
  8. return ((int)(dHh*60.0) + iMm);
  9. }

 
 
Doit y avoir plus simple :(


---------------
VT ... Vaucluse / Vrille(euse :sarcastic: ) c'est pareil tant qu'il y a l'humour :D
n°234186
sielfried
Posté le 25-10-2002 à 00:09:35  profilanswer
 

VisualC++ a écrit a écrit :

ca ca marche mais galere entre float et double et int pour la precision (d ou le pb de 30.0 qui passe a 29)
 

Code :
  1. int g_fniHhmmToMin(double dHhmm)
  2. {
  3. char buffer[50];
  4. double dHh = floor(dHhmm);
  5. double dTmp = (dHhmm - dHh) * 100.0;
  6. _gcvt(dTmp, 10, buffer);
  7. int iMm = atoi(buffer);
  8. return ((int)(dHh*60.0) + iMm);
  9. }

 
 
Doit y avoir plus simple :(
 




 
En effet ça marche... et en effet y'a plus simple. En fait il suffit de passer une valeur double au lieu de float pour que ça fonctionne. Avec ma fonction de départ ça marche aussi. J'avais essayé tout mais pas ça :/
 
Je sais pas, lors de la multiplication par 100 il doit y avoir un arrondi bancal de fait avec le type float, genre le nombre vaut en fait 54.99999999(...), que le débugger arrondit à 55.0000 mais que le transtypage en int tronque en 54 (d'où l'apparente incohérence de l'affichage du débugger).
 
Cela dit si qqun peut m'expliquer de façon un peu plus technique l'origine de la couille lorsque j'utilise un float, c'est encore mieux.
 
Merci à vous deux en attendant :jap:


---------------
StarCraft Professional Gaming Database | [Ze Topic] Starcraft/BroodWar
n°234195
sielfried
Posté le 25-10-2002 à 00:57:59  profilanswer
 

Bah en fait non, ça merde. Ca marche avec 1.55, mais par ex. pas sur 12.20. Par contre avec ta fonction ça a l'air bon qqsoit le nombre :sweat:  
 
Le pb c'est que vu que chui en première année de DUT info (c'est pour un projet), je dois me limiter le + possible à ce qu'on a vu pour le moment (même si je comprends ta fonction), et ta solution paraîtrait un peu compliquée :/


---------------
StarCraft Professional Gaming Database | [Ze Topic] Starcraft/BroodWar
n°234246
sielfried
Posté le 25-10-2002 à 03:01:14  profilanswer
 
n°234257
Musaran
Cerveaulté
Posté le 25-10-2002 à 05:07:48  profilanswer
 

Les valeurs flottantes manquent de précision...
Là où on t'affiche 55.00000, c'est peut-être 54.99999.
La solution est effectivement d'ajouter un chouia au flottant avant tronquage.
 
Si tu veux éviter des warnings, rend tes casts float->int explicites !

Code :
  1. int hhmmToMin(float hhmm)
  2. {
  3. int hh= (int)hhmm;
  4. int mm= (int)( (hhmm-hh)*100.f + .5f );
  5. return hh*60 + mm;
  6. }


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
n°234360
sielfried
Posté le 25-10-2002 à 11:26:29  profilanswer
 

Musaran a écrit a écrit :

Les valeurs flottantes manquent de précision...
Là où on t'affiche 55.00000, c'est peut-être 54.99999.
La solution est effectivement d'ajouter un chouia au flottant avant tronquage.
 
Si tu veux éviter des warnings, rend tes casts float->int explicites !

Code :
  1. int hhmmToMin(float hhmm)
  2. {
  3. int hh= (int)hhmm;
  4. int mm= (int)( (hhmm-hh)*100.f + .5f );
  5. return hh*60 + mm;
  6. }






 
Vi, bah ça marche bien avec +.5f, je crois que je vais faire comme ça. Pour les casts implicites, oui, c'est vrai que c'est plus net comme ça. Plus lisible et plus de warning.
 
Thx :jap:


---------------
StarCraft Professional Gaming Database | [Ze Topic] Starcraft/BroodWar

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  [C] Problème très con sur une fonction apparemment super simple

 

Sujets relatifs
comment faire les tables pour mon problèmeproblème de query ADO embriquées ...
Nouveau problème de conversion[PHP] rendre un parametre optionnel pour une fonction
Probleme d'affichage de Canvas dans un panelnom de la fonction appelante
[C] Probleme de noms de fichier longs....Problème avec une requête SQL
demande de validation d'une fonction en c avec des pointeurs 
Plus de sujets relatifs à : [C] Problème très con sur une fonction apparemment super simple


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR