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

  FORUM HardWare.fr
  Programmation

  Visual C++ 6.0: drôle de bug avec des calculs sur des flottants !

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Visual C++ 6.0: drôle de bug avec des calculs sur des flottants !

n°68330
ZZZzzz
Posté le 29-10-2001 à 23:18:34  profilanswer
 

voilà, j'ai un bug que je n'arrive pas à résoudre..
 
j'ai écrit une procédure qui permet pour un ensemble de sommets (vertices) contenant des coordonnées u,v de texture de faire une interpolation de ces coordonénes u,v vers de nouvelles coordonnées u,v définis par un autre tableau de vertices. Mes sommets sont stockés dans une table que je parcours avec une double boucle i,j linérairement. L'interpolation va en fait rapporcher la coordonnées courante tu ou tv (u,v texture) vers la prochaine coordonnées lui correspondante dans le tableau des nouvelles coordonées. Ce rapprochement se fait par un pas d'incrémentation défini par "inctrans" (un flottant) car les coordonnées u,v (tu et tv donc) varient entre 0.0f et 1.0f.
Le problème est le suivant: certaines coordonées u,v n'atteignent jamais leur valeur de destination, pourtant ma procédure me semble bonne. la voici:
 
"
int completed = 0;
 
for(int j = 0; j < StepMesh+1; j++) {
  for(int i = 0; i < StepMesh+1; i++) {
   if( (CurrentTrans[i + (j*(StepMesh+1))].tu + inctrans) < NextTrans[i + (j*(StepMesh+1))].tu)
    CurrentTrans[i + (j*(StepMesh+1))].tu += inctrans;
   else if( (CurrentTrans[i + (j*(StepMesh+1))].tu - inctrans) > NextTrans[i + (j*StepMesh+1)].tu)
    CurrentTrans[i + (j*(StepMesh+1))].tu -= inctrans;
   else { CurrentTrans[i + (j*(StepMesh+1))].tu = NextTrans[i + (j*(StepMesh+1))].tu; completed++; }
 
   if( (CurrentTrans[i + (j*(StepMesh+1))].tv + inctrans) < NextTrans[i + (j*(StepMesh+1))].tv)
    CurrentTrans[i + (j*(StepMesh+1))].tv += inctrans;
   else if( (CurrentTrans[i + (j*(StepMesh+1))].tv - inctrans) > NextTrans[i + (j*(StepMesh+1))].tv)
    CurrentTrans[i + (j*(StepMesh+1))].tv -= inctrans;
   else { CurrentTrans[i + (j*(StepMesh+1))].tv = NextTrans[i + (j*(StepMesh+1))].tv; completed++; }
  }
 }
"
 
la valeur "completed" contient à la fin le nombre de sommets dont l'interpolation est terminée X 2 (car deux coordonnées par sommets: tu et tv).
 
j'ai remarqué que pour un tableau de taille 2X2, l'erreur survient à la valeur 1,0.tu  (comprendre i= 1, j = 0, coordonnées tu)
 
l'erreur intervient toujours à cet endroit et aussi à d'autres quand le tableau est plus grand.  
J'ai en fait pû vérifier que lors du test "if( (CurrentTrans[i + (j*(StepMesh+1))].tu - inctrans) > NextTrans[i + (j*StepMesh+1)].tu)" le programme semble se tromper dans l'évaluation et entraine donc un mauvais résultat. Par exemple si CurrentTrans[i + (j*(StepMesh+1))].tu = 0.9858, que NextTrans[i + (j*StepMesh+1)].tu = 0.985 et que inctrans = 0.001 alors le compilateur va kan même soustraire inctrans à CurrentTrans[i + (j*(StepMesh+1))].tu et ainsi sa valeur (0.9848) va passer en dessous de celle de CurrentTrans[i + (j*(StepMesh+1))].tu, ce qui n'aurait jamais dû arriver !
à la boucle prochaine inctrans est encore décrémentée à CurrentTrans[i + (j*(StepMesh+1))].tu  (valant ainsi 0.9838 !!) et ce ne sera qu'à la boucle prochaine que sa valeur va être enfin augmenté (à 0.9848) puis rediminuer (à 0.9838) et ainsi de suite !! Je n'y comprend rien ! j'ai essayé de changer la routine en une autre similaire et dans ce cas les erreurs interviennent sur d'autres (i,j)...  
 
kk'un pourrait-il m'aider ?? merci d'avance pour ceux qui feront l'effort d'essayer de comprendre ;) (car je sais que je n'ai aps été très clair) !

 

[edtdd]--Message édité par ZZZzzz--[/edtdd]

mood
Publicité
Posté le 29-10-2001 à 23:18:34  profilanswer
 

n°68331
TheJackal
Posté le 29-10-2001 à 23:22:56  profilanswer
 

desoler g pas trop envie de tous lire mais c juste pour te dire que tous les processeurs sont bugger sur les calculs flotants.
c du a une norme iso pour aller plus vite
je c que quand je faisait 0.000001*1000000 ou un truc dans le genre il me donner un resultat faux
 
ps: source: msdn library

 

[edtdd]--Message édité par TheJackal--[/edtdd]

n°68338
verdoux
And I'm still waiting
Posté le 29-10-2001 à 23:36:44  profilanswer
 

C'est pas clair du tout.
C'est quoi CurrentTrans et NextTrans ?

n°68353
ZZZzzz
Posté le 29-10-2001 à 23:57:34  profilanswer
 

je connait le pb d'imprecision des flottans mais dans mon cas ça m'étonnerai que ce soit ça (ou alors ya vraiment un blem d'utilité des flottants...)
 CurrentTrans et NextTrans sont les tableaux respectif contenant les sommets courants et suivants. Un sommet est uns structure défini par 3 coordonées dans l'espace (x,y et z) et par 2 coordonées pour la texture (tu et tv)... ce sont des sommets d'aobjets 3D en fait (bon je simplifie un peu là). StepMesh représente la dimension de mon tableau (tableau de dimension StepMesh+1 * StepMesh+1). J'espère que ça sera u peu plus clair (mais n'hésitez à demander des précisions kan même) !

 

[edtdd]--Message édité par ZZZzzz--[/edtdd]

n°68362
barbarella
Posté le 30-10-2001 à 00:22:51  profilanswer
 

salut Z,
 
as-tu vérifié que tu avais désactivé l'option de compilateur fastmath (ele a peut-être un autre nom sous C++ 6.0. tjrs est-il que pour executé plus vite les flottant les compilateur intègrent des lib de calcul qui ne respecte pas completement le format IEEE, mais si je me rapelle bien dans certains cas l'erreur de précision peut devenir enorme.
 
Sinon essaie de voir si en jouant avec les options de compil ça change qquechose.

n°68364
barbarella
Posté le 30-10-2001 à 00:27:17  profilanswer
 

pour ton code,
 
tu voudrais pas nous le réecrire avec des intentationn compelte et une variable a = i + (j*(StepMesh+1)). On y gagnerais en clarté.

n°68366
youdontcar​e
Posté le 30-10-2001 à 00:33:16  profilanswer
 

ça m'a plutôt l'air de venir du code en lui-même. tu itères avec une constante plutôt que de faire une interpolation linéaire. si tu avais codé des fades en 256 couleurs, tu verrais le problème :D : les valeurs sources les plus proches de celles de destination atteindront celles-ci plus vite, les autres mettront pas mal de temps -> le temps total pour faire l'interpolation est dépendant de tes données. traduit en fade noir->image, ça fait pas bô, les couleurs passent par le gris avant de se colorer.
 
donc, interpolation linéaire de a vers b : on fait varier un coeff de 0 à 1, v :
valeur interpolée : a*(1-v) + b*v (ou a + (b-a)*v)
 
donc, soit meshA et meshB les deux meshs, stepMesh la mesh interpolée, v le coeff d'interpolation (de 0 à 1)
 
stepMesh[i].tu = meshA[i].tu*(1-v) + meshB[i].tu*v
 
et vala ...

n°68368
ZZZzzz
Posté le 30-10-2001 à 00:50:43  profilanswer
 

youdon'tcare> je sais c pas un interpolation linéraire.. mas c voulu (en fait j'ai pas voulu me prendre la tête et je pense que finalement le fait que certaines valeurs arrivent à destination avant d'autres n'est pas plus mal. C pour cela qu'il y a une varaible "completed"... et puis cela n'explique pas le mauvais fonctionnement de ma procédure non ?
 
barballera> je vais regarder pour les options, sinon pour mon code je pense pas que remplacer Trans[...] par a clarifie grand chose puisque je dois garder Trans[...] pour les affectations. Je pense qu'un copier-coller dans un fichier .txt devrait déjà rendre les choses plus lisibles ;) !

n°68370
ZZZzzz
Posté le 30-10-2001 à 00:51:54  profilanswer
 

barbarella> en y repensant je compile actuellement en mode debug, donc ya pas d'optimisation et à fortiori pas d'option /fastmath (j'ai vérifié j'ai pas vu de choses semblables)

n°68386
barbarella
Posté le 30-10-2001 à 08:42:17  profilanswer
 

slt,
 
tes flottants sont en précision single ? si oui, quand tu passes a double ça change qque chose ?

mood
Publicité
Posté le 30-10-2001 à 08:42:17  profilanswer
 

n°68421
ZZZzzz
Posté le 30-10-2001 à 11:07:27  profilanswer
 

le pb c que la structure d'un sommet n'est défini qu'avec es flottans simple précision. Je ne peux pas les passer en double. je peux faire les calculs (et inctrans) en double mais je doute que ça ne change kkchose au résultat. je vais kan même essayer.

n°68424
ZZZzzz
Posté le 30-10-2001 à 11:11:26  profilanswer
 

non, ça ne change rien ...

n°68428
barbarella
Posté le 30-10-2001 à 11:21:23  profilanswer
 

slt,
 
de toute façon il n'y pas 36 solutions. Si ton algo est bon, alors c'est le compilateur qui se mélange les pinceaux. Lorsque ça m'arrive, je réécris l'algo d'une autre façon. Généralement je tente :
 
1 - de simplifier les expressions pour simplifier la vie du compilateur, d'ou l'idée du a = ...  
 
2 - je décompose plus l'algo, quand c'est possible.
 
sinon je ne vois pas comment d'aider plus, hormis vérifier les déclaration de tes variables et leur initialisation. Récement j'ai fait un cauchemar, j'assimilais tous les long a des unsigned int :D, et je modifiais des dizaines de millier de lignes pour remplacer les long par des int, pour un prog qui doit tourner sur des microprocesseur IA-32 je te raconte pas de l'interet :D

n°68435
ZZZzzz
Posté le 30-10-2001 à 11:33:52  profilanswer
 

:D pas marrant en effet ...  
bon bah merci Barbarella, je vais essayer de l'écrire autrement (je l'avais déjà fait mais peut-être pas assez différent). Il est apparement clair que c le compilo qui s'embrouille car je viens de tester l'algo sur un prog à part (qui ne fait que ça) et j'ai la même erreur... ça ne viens donc pas de pb d'allocations mémoire...

n°68436
barbarella
Posté le 30-10-2001 à 11:34:37  profilanswer
 

ok,
 
je viens de refaire l'intentation de ton algo chez moi et j'ai remplacé tous tes i + j*(StepMesh+1)) par une variable a. devinnes ce que j'ai trouvé, ca !
 
i + (j*StepMesh+1)
 
or je suppose que ça devrait être i + (j*(StepMesh+1)) a cause de l'ordre des opérateurs. La mul j*StepMesh sera faite avant le StepMesh+1.
 
voir :if( (CurrentTrans[i + (j*(StepMesh+1))].tu - inctrans) > NextTrans[i + (j*StepMesh+1)].tu)  
 
 
Si c'est ça, de grace travaille la lisibilité de tes prog ;)

 

[edtdd]--Message édité par barbarella--[/edtdd]

n°68442
ZZZzzz
Posté le 30-10-2001 à 11:42:01  profilanswer
 

encre merci !  
j'ai simplement fait comme tu as dis (j'ai stocké mes valeurs de tab dans des variables) et c apparement suffisant pour corriger le pb ;) !!
 
drôle de bug kan même :mouais: ...

n°68446
barbarella
Posté le 30-10-2001 à 11:45:30  profilanswer
 

ouais,
 
donc le bogue était bien le i + (j*StepMesh+1) en faisant a =i + (j*(StepMesh+1)) tu l'as implicitement corrigé

n°68579
ZZZzzz
Posté le 30-10-2001 à 19:18:21  profilanswer
 

non car en fait voilà ce n'est pas ça que j'a imodifié. J'ai directement stocké la valeur de Trans[...].tu et NextTran[].tu dans des variables.
 
voilà la modif qui fonctionne:
 
"
for(int j = 0; j < StepMesh+1; j++) {
  for(int i = 0; i < StepMesh+1; i++) {
 u = CurrentTrans[i + (j*(StepMesh+1))].tu;
 v = CurrentTrans[i + (j*(StepMesh+1))].tv;
 nu = NextTrans[i + (j*(StepMesh+1))].tu;
 nv = NextTrans[i + (j*(StepMesh+1))].tv;
     
 if( (u + inctrans) < nu)
     CurrentTrans[i + (j*(StepMesh+1))].tu += inctrans;
 else if( (u - inctrans) > nu)
   CurrentTrans[i + (j*(StepMesh+1))].tu -= inctrans;
 else  
          { CurrentTrans[i + (j*(StepMesh+1))].tu = nu; completed++; }
 
 
 if( (v + inctrans) < nv)
   CurrentTrans[i + (j*(StepMesh+1))].tv += inctrans;
 else if( (v - inctrans) > nv)
   CurrentTrans[i + (j*(StepMesh+1))].tv -= inctrans;
 else
          { CurrentTrans[i + (j*(StepMesh+1))].tv = nv; completed++; }
 
}
}
"
 
à vrai dire je vois pas ce que ça change dans l'algo, mais maintenant ça fonctionne :) !!

n°68580
ZZZzzz
Posté le 30-10-2001 à 19:26:13  profilanswer
 

je viens de me rendre compte que ma réponse ne contredit pas la tienne, cependant je comprend pas pourquoi il y aurait eu un bug au niveau de i + (j*StepMesh + 1) ... et les résultats étaient vraiment bizarres... le bug avait lieu quand i >= (j-2)mod(StepMesh) ou un truc du genre :??: ...

n°68582
barbarella
Posté le 30-10-2001 à 19:36:34  profilanswer
 

Z,
 
une expression du genre (A*B+1) <> (A*(B+1)) c'est a cause de l'ordre de priorité des opérateurs. La multiplication passe avant l'addition. Remarque dans ce cas c'est encore plus simple, le compilateur voit la multiplication avant l'addition.
 
Tu devais obtenir un résultat bizarre avec ton (j*StepMesh + 1)  
 
je suis sur que si tu reprenais la fonction que tu as donné en début de topic juste en corrigeant le (j*StepMesh + 1) en (j*(StepMesh + 1)) ça marcherait.
 
 
Sinon le jour ou t'auras besoin d'optimisation viens nous voir car je crois qu'on pourra te donner quelques conseils.  
 
---------------------------
L'optimisation n'est pas une technique mais un état d'esprit ;)

n°72613
ZZZzzz
Posté le 15-11-2001 à 21:07:47  profilanswer
 

barbarella> où vois-tu dans ma fonction de départ un " (j*StepMesh + 1)" ? j'ai bien fait attention à mettre " (j* (StepMesh + 1) )" ...
par ailleurs je cherche évidemment à optimiser mes programmes mais en ce qui concerne cet algo cété juste un essai et "StepMesh" restait relativement faible donc ce n'est pas grave s'il elle n'est pas bien optimisé .

n°72620
barbarella
Posté le 15-11-2001 à 21:39:37  profilanswer
 

salut,
 
dans le code que tu nous as donné en début de post  
 
int completed = 0;  
 
for(int j = 0; j < StepMesh+1; j++) {  
 for(int i = 0; i < StepMesh+1; i++) {  
  if( (CurrentTrans[i + (j*(StepMesh+1))].tu + inctrans) < NextTrans[i + (j*(StepMesh+1))].tu)  
   CurrentTrans[i + (j*(StepMesh+1))].tu += inctrans;  
  else if( (CurrentTrans[i + (j*(StepMesh+1))].tu - inctrans) > NextTrans[i + (j*StepMesh+1)].tu)  
   CurrentTrans[i + (j*(StepMesh+1))].tu -= inctrans;  
  else { CurrentTrans[i + (j*(StepMesh+1))].tu = NextTrans[i + (j*(StepMesh+1))].tu; completed++; }  
 
  if( (CurrentTrans[i + (j*(StepMesh+1))].tv + inctrans) < NextTrans[i + (j*(StepMesh+1))].tv)  
   CurrentTrans[i + (j*(StepMesh+1))].tv += inctrans;  
  else if( (CurrentTrans[i + (j*(StepMesh+1))].tv - inctrans) > NextTrans[i + (j*(StepMesh+1))].tv)  
   CurrentTrans[i + (j*(StepMesh+1))].tv -= inctrans;  
  else { CurrentTrans[i + (j*(StepMesh+1))].tv = NextTrans[i + (j*(StepMesh+1))].tv; completed++; }  
 }  
}  
 
 
j'ai mis en gras souligné le méchant vilain canard ;)

 

[edtdd]--Message édité par barbarella--[/edtdd]

n°72762
ZZZzzz
Posté le 16-11-2001 à 13:07:26  profilanswer
 

arf mais tu as raison !! javé po vu :( !!!!
ben voilà cété ça la cause du bug, quel con vraiment... et moi qui suspectait encore le compilateur, chui vraiment nul !!

mood
Publicité
Posté le   profilanswer
 


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

  Visual C++ 6.0: drôle de bug avec des calculs sur des flottants !

 

Sujets relatifs
[Visual Basic] Un exécutable pas exécutableAdd-ins dans Visual C++
faire du grafik sous Visual 6 ?[Visual Basic] - Initialiser un tableau de taille variable
APOSTROPHE DANS UNE REQUETE SQL - VISUAL BASIC[C++ / Templates / Visual Studio] fonction po accessible
[Visual Studio] symbole externe non résoluinstall de glut pour visual C++ 6.0
Visual fox pro : PB de trie sur un grid quand index trop long...[Visual C++ 6] Quid ??? Generator GUID
Plus de sujets relatifs à : Visual C++ 6.0: drôle de bug avec des calculs sur des flottants !


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