CONNEXION
  • RetourJeux
    • Sorties
    • Hit Parade
    • Les + populaires
    • Les + attendus
    • Soluces
    • Tous les Jeux
    • Gaming
  • RetourActu Gaming
    • News
    • Astuces
    • Tests
    • Previews
    • Toute l'actu gaming
  • RetourBons plans
    • Bons plans
    • Bons plans Smartphone
    • Bons plans Hardware
    • Bons plans Image et Son
    • Bons plans Amazon
    • Bons plans Cdiscount
    • Bons plans Decathlon
    • Bons plans Fnac
    • Tous les Bons plans
  • RetourJVTech
    • Actus High-Tech
    • Intelligence Artificielle
    • Smartphones
    • Mobilité urbaine
    • Hardware
    • Image et son
    • Tutoriels
    • Tests produits High-Tech
    • Guides d'achat High-Tech
    • JVTech
  • RetourCulture
    • Actus Culture
    • Culture
  • RetourVidéos
    • A la une
    • Gaming Live
    • Vidéos Tests
    • Vidéos Previews
    • Gameplay
    • Trailers
    • Chroniques
    • Replay Web TV
    • Toutes les vidéos
  • RetourForums
    • Hardware PC
    • PS5
    • Switch 2
    • Xbox Series
    • Switch
    • Pokemon pocket
    • FC 25 Ultimate Team
    • League of Legends
    • Tous les Forums
  • PC
  • PS5
  • Xbox Series
  • Switch 2
  • PS4
  • One
  • Switch
  • iOS
  • Android
  • MMO
  • RPG
  • FPS
En ce moment Genshin Impact Valhalla Breath of the wild Animal Crossing GTA 5 Red dead 2
Liste des sujets

(C/C++) Traitrise des tests d'égalité

JeanYvesYves
JeanYvesYves
Niveau 10
12 juillet 2005 à 11:18:51

Voici un piege a éviter absolument si vous programmez en C/C++ sur les tests d´égalités :

- ne JAMAIS faire de tests d´égalités entre float ou entre double...
J´illustre :

compilez ce programme :

  1. include < iostream>

using namespace std;
int main()
{
double a=0.1;
a*=3;
if ( a==0.3)
cout < < " ok" < < endl;
else
cout < < " NON ! !" < < endl;
return 0;
}

Testé sous Visual C++. vous vous prenez le " non"...
Car en effet, la machine ( et surtout pour 0.3, lol ! question de codage de mantisse...) n´est pas exacte sur le codage des double et des float :
En réalité, a*3 donnera peut etre, en machine : 0.30000000000000000000001 ce qui est différent, et pourtant tellement proche...

Pour les double et les float, on n´utilise pas == mais > = et < =.
Si vous voulez tester l´égalité, il faut tester si la différence entre les deux est infiniment proche :

double epsilon=0.000000001;
if ( fabs(a-0.3)<epsilon))

- ne JAMAIS faire de tests d´égalités sur les temps.
Certaines libs ( SDL pour ne pas la citer) proposent de gérer des chronos, dont les résultats sont des int, et faits en millisecondes.
Imaginons que vous vouliez faire une fonction qui attend 5 secondes :

tempscourant= GetChrono(); / / a vous de mettre la bonne fonction
while(GetChrono()!=tempscourant+5000)
{
}

Cette fonction est fausse : en effet, si jamais votre machine subit un ralentissement, vous risquez de ne jamais avoir GetChrono()==tempscourant+5000...
vous aurez GetChrono()==tempscourant+4999, puis au prochain test : GetChrono()==tempscourant+5001...
et la vous etes mort, vous ne sortirez jamais du while....
Donc, jamais de == pour des tests de timming, mais des < = et des > =...
La fonction se corrige donc ainsi :

tempscourant= GetChrono(); / / a vous de mettre la bonne fonction
while(GetChrono()<=tempscourant+5000)
{
}

Et la, vous sortirez quoiqu´il arrive...

Ptival
Ptival
Niveau 10
12 juillet 2005 à 12:17:50

Pour la deuxième ça me paraît logique :)

Pour la première par contre c´est sûr que c´est un piège à éviter ; )

De même faire attention avec les opérandes d´un opérateur :

tab[i] = f1();

Si la fonction f1 modifie i, on n´est pas sur de modifier tab[i] et non pas tab[i_modifié_par_f1] ! !!
( Mais bon ça en soi-même c´est très moche donc on ne le fait pas :lol: )

sonic66
sonic66
Niveau 10
12 juillet 2005 à 15:09:51

un float , ca represente quoi ce mot? ^^

JeanYvesYves
JeanYvesYves
Niveau 10
12 juillet 2005 à 15:11:36

float : nombre a virgule flottante = nombre a virgule ( faible précision) ( 4 octets)
double : nombre a virgule flottante double précision = nombre a virgule ( forte précision) ( 8 octets)

Nobuo_Uematsu
Nobuo_Uematsu
Niveau 3
12 juillet 2005 à 17:38:07

" #include < iostream>
using namespace std;
int main()
{
double a=0.1;
a*=3;
if ( a==0.3)
cout < < " ok" < < endl;
else
cout < < " NON ! ! " < < endl;
return 0;
} "

je vois que de la precision double là dedans

dnob700
dnob700
Niveau 10
12 juillet 2005 à 17:49:34

Une autre erreur à éviter :

Dans tout ce qui suis, n est un double.

un jour je tape ça :
if ( n<2) fait_machin1();
if ( n>=2) fait_machin2();

Vous pourriez me dire que c´est bête il suffirait de faire un else et ça revient au même. Pourtant dans mon cas ni machin ni machin2 n´était exécuté à chaque fois que je passait pas ce test.

Tout simplement car j´avais fait une erreur de calcul en amont ( genre n/=0; mais en moins visible) et donc que n n´était plus un nombre ( on appelle ça un NAN ( Not a Number)) et par conéquent tout les test faire avec n sont faux ( sauf celui is_nan(n) ( si jamais ça existe)).

donc ( n<2) est toujours faux mais ( n>=2) aussi ( bien sur leur négation avec ! sont vrai).

Donc quand vous faites des calculs avec des réel ( ou des entiers) comme des divisions, ou des calcul plus complexe de trigo par exemple ou des log ou plein d´autre chose, il faut vérifier qu´une erreur ne s´est pas glissé dans votre calcul et que vos variables représente toujours des nombres et pas autre chose ( un NAN par exemple ou alors ça peut valoir l´infini mais dans ce cas là les test marcheront toujours ( c´est les calculs qui deviendront étrange).

mcbroly
mcbroly
Niveau 7
12 juillet 2005 à 20:07:15

:ouch2: sa a l´air archi compliqué le C!!

fil_razorback
fil_razorback
Niveau 10
12 juillet 2005 à 20:15:24

dnob :d) on a exactement la meme chose en actionscript avec les NaN, ca arrive notamment si on fait des trucs comme ca:
a= 5;
b= undefined; ( a cause d´une faute de frappe ou une merde comme ca)
c = a*b;
trace(c);

et zou NaN dans le panneau de sortie :)

Lapintade
Lapintade
Niveau 30
12 juillet 2005 à 22:51:31

Merci pour ces tuyaux JYY.

Pour les float, il faut en effet toujours travailler avec des Epsilons.

Pour les if . .. c´est bien de toujours prevoir le else, c´est plus propre. Ca permets de mieux maitriser tous les cas possibles et de mieux tester/debugger la fonctions.

Hier je me suis fait avoir avec un truc terrible aussi. Dans mon code, j´ai fait une fonction sndPlaySound(int a). Elle marchait bien dans un source et pas dans un autres, probleme de link. Au bout d´une heure, je me suis rendu compte que c´etait une fonction qui existait deja dans un . h de windows. Pas de chance quand meme :)

Sinon dans le meme style, je suis deja tombé sur le bug de la mort qui tue, avec l´operateur virgule ( il est peu connu celui la mais il existe en C).
adresse = a , b , c , d;
donne adresse=d ( le dernier argument).
C´est con et ca sert a rien ! Sauf a faire de grosses erreurs quand on s´est pas rendu compte qu´on a mis une virgule en trop ou une parenthese en trop ( ca indique aucune erreur a la compil).

MrGoTo
MrGoTo
Niveau 8
12 juillet 2005 à 23:42:09

Bon moi je donne deux tuyaux que j´ai appris au stage de cet été.

1) Le nom des variables.
Dans un but de lisibilité toujours employer des noms de variable explicite car même si c´est plus long à ecrire si on a une erreur ça saute aux yeux.
Exemple:
---------------------------
int matrice[5][10];

for ( int i = 0; i < 5; ++i)
for ( int j = 0; j < 10; ++j)
matrice[j][i] = i * j;
---------------------------

Paf overflow. Ici le probleme saute aux yeux, normal ya 4 lignes de code. Quand yen a plus on peut passer des minutes à chercher.
Maintenant avec des noms explicites.

---------------------------

  1. define NBLIGNE 5
  2. define NBCOLONNE 10

int matrice[NBLIGNE][NBCOLONNE];

for ( int ligne_courante = 0; ligne_courante < 5; ++ligne_courante)
for ( int colonne_courante = 0; colonne_courante < 10; ++colonne_courante)
matrice[colonne_courante][ligne_courante] = ligne_courante * colonne_courante;
---------------------------

La le bug devient plus simple à cerner et le code se passe completement de commentaires.

2) Eviter d´ecrire deux fois le même bout de code.
Lors des grosses expressions:
if
(matrice[ligne_courante+indice_ligne][colonne_cour
ante*2+indice_colonne] == 3)
else if ( ..la meme chose..)
La on utilise des variables temporaires.
Pareil avec les valeurs suivant les cas.
-------------------
if ( lettre == 1)
cout < < " a";
if ( lettre == 2)
cout < < " b";
-------------------
Ici on fait un tableau contenant chaque lettre associée au cas.
char lettres[2] = { ´a´, ´b´ };
Et enfin
cout < < lettres[lettre];

Voila puis-ce ces conseils vous etre utiles.

PS: fuck jv parser

Nobuo_Uematsu
Nobuo_Uematsu
Niveau 3
13 juillet 2005 à 00:17:57

l´heure est aux trucs qui evitent de galerer pendant des heures :)

- comme l´a dit lapindtade, tjrs verifier si les fonctions n´existent pas dans un header du compilo ! !!

- " int 3DVector" retournera une erreur. les noms de variables en C++ doivent absolument commencer par une lettre ( c con mais c´est jamais expliqué :).

- tjrs faire if(Data ! = NULL) avant de faire un delete. Le C++ ou la loi de l´arbitraire, avec la memoire ca marche un peu quand ca veut.

--
et pr finir sur l´OpenGL, en 2D
- lorsque vous etes en 2D si vous voulez utiliser votre espace de travail comme surface parfaite ( c.a.d unités proportionelle), specifiez dans la fonction glOrtho le rapport width/height ! !! Sinon gare aux maux de tetes lors des rotations deformées :) !

fil_razorback
fil_razorback
Niveau 10
13 juillet 2005 à 09:16:28

" 2) Eviter d´ecrire deux fois le même bout de code.
Lors des grosses expressions:
if

(matrice[ligne_courante+indice_ligne][colonne_cour

ante*2+indice_colonne] == 3)
else if ( . .la meme chose..)
La on utilise des variables temporaires.
Pareil avec les valeurs suivant les cas. "

C´est pour une question de lisibilité " seulement" ( au final c´est plus lent non)?

BigGamer95
BigGamer95
Niveau 10
13 juillet 2005 à 11:21:46

Un autre piege a eviter absolument

eviter de lire ce topic le matin quand vous etes mal reveillé ou vous aurez comme moi un enorme mal de tete

en tt cas, c´est pas mal comme topic ( sauf pour la tete le matin :fou: )

dnob700
dnob700
Niveau 10
13 juillet 2005 à 16:12:13

fil, je pense pas qu´il y ait de perte de perf :

si tu écrit moins parce que tu précalcule certaines choses, c´est du calcul économisé :

par exemple dans
if ( f1(x)==0)
machin();
else if(f1(x)>0&&2(x)!=5)
machin2();

ici tu as mis effectue plusieurs fois f1(x) et c´est peut-être une opération très longue. Mais de toute manière tu doit l´effectuer au moins une fois. Donc tu peut faire :
int temp=f1(x);
if ( temp==0)
machin();
else if(temp&&2(x)!=5)
machin2();

par contre f2(x) n´est calculé qu´une seule fois au maximum ou zéro fois. Donc il ne vaut mieux pas le précalculer.

Autre chose :
Le C++ fait ce qu´on appelle une évalutation paresseuse des test ( je crois qu´on appelle ça comme ça). C´est à dire que si vous faites :

if ( f1(x)&&2(x)&&3(x)...)
alors il ne va pas évaluer toutes l´expression mais juste f1(x) et si c´est vrai alors il va passer à f2 etc. Mais dès qu´il en croise un qui est faux alors il va s´arrèter. ( de même si c´est des || dans ce cas là il s´arrète dès qu´il y en a un qui est vrai).
Ca sers à deux chose. D´abord les effets de bord : vous ne devez jamais effectuer d´opération globale dans ce genre d´appel ( dans les fx) car vous ne pouvez pas êtres sur que les fonctions seront exécuté. Mais ça c´est du bon sens. Par contre pour l´optimisation, on peut supposer quand c´est bien écrit que le compilateur évalue ces expression dans l´ordre où on les écrit donc il faut les classer dans l´ordre qui sera le plus rapide. Par exemple si toutes les fonctions ont la même probabilité d´être vraie ou fausse alors il faut mettre au début la plus rapide etc. Pour que si jamais ça s´arrète vite on ait évalué les fonction rapide et pas les très lente.
Si on contraire toute les fonction ont la même durée mais que certaine ont de grande chance de renvoyé la valeur qui va faire s´arréter l´évalutation ( faux pour des && et vrai pour des ||) alors il faut aussi la mettre au début pour économiser des appels.

Sous forums
  • Aide à l'achat Mac
  • Internet
  • Macintosh
  • Création de sites web
  • Création de Jeux
  • Linux
  • Programmation
  • Steam Deck
  • Hardware
La vidéo du moment