Erreur de calcul sur float

Bonjour à tous.

J'ai un (petit) problème de calcul sur du float que je n'arrive pas ni à résoudre, ni à comprendre. Voila le problème:

J'ai une fonction avec juste cette partie qui pose problème:

  float compensation;
  compensation = (0,021 * 361);
  Serial.println(" --- entrée entrée de fonction ---");
  Serial.print("compensation = ");
  Serial.println(compensation);

Si j'exécute ça, la sortie sur la console me donne

 --- entrée entrée de fonction ---
compensation = 6137.00

Ce n'est pas tout à fait le résultat auquel je m'attend...
Pensant à un problème sur la valeur 361 qui pourrait forcer le calcul en "int", j'ai tenté ça:

  float compensation;
  compensation = (0,021 * 361.0);

Hélas, le résultat est pire:

 --- entrée entrée de fonction ---
compensation = 0.00

J'avous y perdre mon latin. Petite précision qui a son importance: je suis sur un arduino nano.

Merci de votre aide, parce que la, je sèche.
Rémi.

bonsoir,

il faut mettre un point à la place de la virgule.
compensation = (0.021 * 361.0);

Bonne soirée.

Tout a fait ça

Quand le. Compilateur rencontre (0,021 * 361.0) il voit deux expressions séparées par l’opérateur virgule.

La première expression 0 est évaluée et ne fait rien donc l’optimiseur va la dégager.

Il reste (021 * 361.0). En C ou C++ quand on note un nombre en commençant par 0 ça veut dire qu’il est exprimé est octal (base 8) donc 021 c’est 17 en décimal. Le compilateur calcule donc 17x361=6137 donc la valeur que vous voyez est bonne

:slight_smile:

La bonne notation

const float compensation = 0.021 * 361.0;  // ici un commentaire explicatif sur les valeurs 

@J-M-L @philippe86220
Merci à vous deux.
J'étais persuadé que c'était la virgule, et je n'ai vraiment pas pensé à ça!!!!
Et le compilateur n'a rien dit, bien sur.

Je peux confirmer que ça marche mieux en plus.... :slight_smile: Et si je vous dit que la compilation est plus rapide, vous me croyez? ou c'est moi qui yoyote?
En tout cas, merci encore.

bien sûr c'est vite dit...mouais... ça c'est parce que vous n'avez pas activé les warnings dans les préférences..

si je compile cela

void setup() {
  float compensation;
  compensation = (0,021 * 361.0);
  Serial.begin(115200); Serial.println();
  Serial.println(compensation);
}
void loop() {}

le compilateur me prévient que je fais sans doute une erreur

sketch_nov06a.ino: In function 'void setup()':
sketch_nov06a.ino:4:28: warning: left operand of comma operator has no effect [-Wunused-value]
   compensation = (0,021 * 361.0);
                            ^~~~~

si vous compilez pour ESP32 ce sera même traité comme une erreur et la compilation va s'arrêter.

et si vous indentez le code vous verrez que l'écriture se transforme en

  compensation = (0, 021 * 361.0);

montrant bien avec un espace qu'il y a sans doute un souci à ce niveau

Bonsoir @rsuinux,
Je m'adresse uniquement à vous car @J-M-L est incollable, il connait tout sur la programmation des microcontrôleurs !

ou
float const compensation = 0.021 * 361.0;

ou encore
float const compensation { 0.021 * 361.0 };

Bonne soirée à vous et à @J-M-L

on peut même mettre constexpr au lieu de const ! que de possibilités :slight_smile:

euh...
images

@philippe86220 @J-M-L
Ah, bien vu le coup de la constante!
mais quelle est la différence entre constexpr et const?

bonsoir @rsuinux,

Le mot clé constexpr indique au compilateur qu’une variable (ou fonction) peut déjà être évaluée pendant la compilation et non plus seulement à l’exécution du programme. L’avantage c’est que le compilateur effectue le travail une fois pour toutes, ce qui rend l’exécution du programme plus rapide.
En déclarant des constantes avec constexpr, on les rend utilisables à la compilation :

constexpr float const compensation = 0.021 * 361.0;
constexpr  float const compensation { 0.021 * 361.0 };

Le qualificatif constexpr indique que la donnée qualifiée est constante, ce qui permet de l'utiliser dans une expression à résultat constant. Comme dit plus haut, Le compilateur précalcule le résultat à des fins d'optimisation.
En fait les variables déclarées constexpr ont un statut semblable à celui des littéraux (tels que les constantes numériques). Toutefois contrairement aux littéraux, elles résident en mémoire : on peut donc obtenir leur adresse. Elles doivent être des données de types primitifs (int, double, pointeurs ...) ou des agrégats composés de données de types primitifs. Elles peuvent aussi être des objets, à condition que la classe correspondante ait un constructeur également déclaré constexpr.

Implicitement, utiliser constexpr sur une variable revient à la déclarer const, ce qui est logique. Dans le but d'être explicite, on peut préciser également const mais ce n'est pas une obligation :

constexpr int k = 3;

constexpr  float   compensation = 0.021 * 361.0; 

Bonne soirée.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.