[C++] Type entier vers flottant.

Résolu
NeriXs Messages postés 258 Date d'inscription lundi 4 mai 2015 Statut Membre Dernière intervention 27 février 2024 - Modifié le 13 nov. 2019 à 21:00
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 - 15 nov. 2019 à 18:46
Bonjour,

Quelqu’un pourrait m’expliquer comment modifier cette constante pour que le résultat affiche un arrondie au plus proche à 2 chiffres après la virgule ?

//Extrapolation de 173° à 180° = 2559,306358381503
 
const int T180=520+(((2480-520)/173)*180);


Ici 2559,31

Merci pour votre aide.

21 réponses

NHenry Messages postés 15112 Date d'inscription vendredi 14 mars 2003 Statut Modérateur Dernière intervention 13 avril 2024 159
7 nov. 2019 à 22:56
Déjà, ne pas utiliser un entier (qui par définition n'a pas de partie décimale).
Tu peux utiliser un flottant (simple ou double précision)
Puis pour l'arrondi, cela est à faire à l'affichage.
0
NeriXs Messages postés 258 Date d'inscription lundi 4 mai 2015 Statut Membre Dernière intervention 27 février 2024 1
8 nov. 2019 à 06:52
J’avoue être un peu largué, auriez-vous un petit exemple concret ?
0
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
Modifié le 8 nov. 2019 à 16:47
Bonjour.

Un entier (int) ne contient que des nombres sans virgules. int a = 10/4 donnera 2.
Pour conserver la partie décimale, il faut utiliser un type décimal. double a = 10/4 donnera 2.5

Pour l'affichage, en C++, rien de particulier à faire, il sera déduit.
Donc std::cout << a << std::endl affichera bien 2.5 (par exemple).

En C, ou dans d'autres langages, il aurait fallu préciser le type d'affichage en plus d'utiliser le bon type (ce que voulait dire NHenry). Exemple:
printf("%f", a); => 2.5
printf("%d", a); => 2


0
NeriXs Messages postés 258 Date d'inscription lundi 4 mai 2015 Statut Membre Dernière intervention 27 février 2024 1
8 nov. 2019 à 14:11
Les valeurs affichées sont bonnes:

Bienvenue sur le moniteur série.
L'extrapolation à 180°, de 173° entre la butée mini: 520 µS et la butée maxi: 2480 µS est égale à: 2559.31 µS.
1° est égale à 11.33 µS.

0° = 520.00 µS
1° = 531.33 µS
173° = 2480.00 µS
180° = 2559.31 µS


Je ne suis vraiment pas sûr que ma gestion soit faite dans les règles de l'art.

#include <Servo.h>

const byte ServoPin = 10;
const int LowerPos = 520 ; //Butée Mini du servo
const int UpperPos = 2480 ; //Butée Maxi du servo
const int Range = 173 ; //Plage de déplacement en degrés
const float T180 = LowerPos + (((float)(UpperPos - LowerPos) / Range) * 180) ; //Extrapolation à 180° = 2559,306358381503
const float UsRange = (T180 - LowerPos) / 180 ; // 1° = 11,32944444444444 µS

Servo myservo;  // create servo object to control a servo
void setup() {
  Serial.begin(115200);
  myservo.attach(ServoPin, LowerPos, T180);
  Serial.println("Bienvenue sur le moniteur série.");
  
  Serial.print("L'extrapolation à 180°, de ");
  Serial.print(Range);
  Serial.print("° entre la butée mini: ");
  Serial.print(LowerPos);
  Serial.print(" µS et la butée maxi: ");
  Serial.print(UpperPos);
  Serial.print(" µS est égale à: ");
  Serial.print (T180);
  Serial.println(" µS.");

  Serial.print("1° est égale à ");
  Serial.print(UsRange);
  Serial.println(" µS.");
  Serial.println();

}

void loop() {
  int PosDeg = Serial.parseInt(); // PosDeg = la position saisie dans le moniteur série de 0 à 173°
  float PosUs = LowerPos + (PosDeg * UsRange); // degré en µS
  if (Serial.available() > 0) {
    Serial.print(PosDeg);
    Serial.print("° = ");
    Serial.print(PosUs,2);
    Serial.println(" µS");

  }
    clearSerialBuffer();  
}

void clearSerialBuffer() {
  //clear serial buffer (but do nothing with it)
  while (Serial.available())
  {
    Serial.read();
  }
}


N'hésitez pas me reprendre ou me corriger si besoin!
Merci
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
8 nov. 2019 à 14:28
Si tu as le choix, préfère les double aux float, la précision est bien meilleure. Si tu es sur de l'embarqué où l'économie de taille est de mise, alors conserve les float.

Évite les variables globales, c'est assez crade (les const globales c'est tout à fait ok, mais la variable "myservo" ne devrait pas se balader en global).

Pour le reste, si tu peux faire un seul appel à print avec tout dedans plutôt que N print à la suite, ça serait sous doute plus efficace niveau perfs (même si je te l'accorde, ça sera un gain marginal pour ce cas-ci).
0
NeriXs Messages postés 258 Date d'inscription lundi 4 mai 2015 Statut Membre Dernière intervention 27 février 2024 1
8 nov. 2019 à 14:50
Je ne suis pas arrivé au résultat voulu avec les doubles, certainement par mon manque de connaissance et d'expérience! pourriez-vous me reprendre?
0
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
8 nov. 2019 à 14:59
J'aurais bien du mal à voir ce qui se passe à l'aveugle :(.
Quel résultat attendais-tu ? Quel résultat as-tu obtenu à la place ?
Qu'as-tu fait exactement dans ton code ?
0
NeriXs Messages postés 258 Date d'inscription lundi 4 mai 2015 Statut Membre Dernière intervention 27 février 2024 1
8 nov. 2019 à 15:53
Désolé je ne retrouve pas mon bout de code.
J'avais utilisé ce qu'on appelle les virgule fixe en travaillant sur des entiers multiplier par 100 pour avoir mes deux chiffres après la virgule.
Mis en place une égalité en type double puis une division de 100 après traitement.
Dans le code actuel le résultat voulut est là, mais je ne suis vraiment pas sûr d'avoir utilisé mes "float" comme il se doit!
0
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
8 nov. 2019 à 15:56
Cette technique n'est pas gênante. On fait cela dans des systèmes où l'on veut utiliser des entiers car il n'y a pas besoin d'une grande précision (2 après la virgule c'est peu de précision d'un point de vue décimal).
Sur le principe, ça me paraît correct. Mais je ne peux te le confirmer sans voir le code.
0
NeriXs Messages postés 258 Date d'inscription lundi 4 mai 2015 Statut Membre Dernière intervention 27 février 2024 1
8 nov. 2019 à 18:13
Pouvez-vous m’expliquer comment évolue le calcule de mon programme ?
Je pars de 520 pour aller a 2480 soit de 0° à 173°.
Le programme commence bien a 520 pour 0.
Et fini bien a 2480 pour 173.
Je remarque une perte à partir de 10 de l’ordre de 0,01.

Avec un incrément de 11,32944444444444 pour 1 degré.
Je devrais arriver à 520 + (173 * 11,32944444444444) = 2 479,993888888888
0
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
8 nov. 2019 à 18:28
Difficile de t'aider sans voir ton code :(
Je ne sais pas si tu t'en rends compte qu'on n'est pas équipé de boules de cristal :p

Par intuition, je dirais que ça ressemble à un problème d'imprécision décimale, donc utiliser des double à la place des float pourrait aider. Le calcul que tu fais n'est peut être aussi pas adapté et pourrait être amélioré pour diminuer l'imprécision.

Mais encore une fois, impossible de t'aider avec aussi peu d'informations...
0
NeriXs Messages postés 258 Date d'inscription lundi 4 mai 2015 Statut Membre Dernière intervention 27 février 2024 1
8 nov. 2019 à 19:15
Le code est en poste 4.
0
NeriXs Messages postés 258 Date d'inscription lundi 4 mai 2015 Statut Membre Dernière intervention 27 février 2024 1
13 nov. 2019 à 18:54
@cptpingu
Que pensez-vous de mon code ?

#include <Servo.h>

const byte ServoPin = 10;
const int LowerPos = 520 ; //Butée Mini du servo
const int UpperPos = 2480 ; //Butée Maxi du servo
const int Range = 173 ; //Plage de déplacement en degrés
const float T180 = LowerPos + (((float)(UpperPos - LowerPos) / Range) * 180) ; //Extrapolation à 180° = 2559,306358381503
const float UsRange = (T180 - LowerPos) / 180 ; // 1° = 11,32944444444444 µS

Servo myservo;  // create servo object to control a servo
void setup() {
  Serial.begin(115200);
  myservo.attach(ServoPin, LowerPos, T180);
  Serial.println("Bienvenue sur le moniteur série.");
  
  Serial.print("L'extrapolation à 180°, de ");
  Serial.print(Range);
  Serial.print("° entre la butée mini: ");
  Serial.print(LowerPos);
  Serial.print(" µS et la butée maxi: ");
  Serial.print(UpperPos);
  Serial.print(" µS est égale à: ");
  Serial.print (T180);
  Serial.println(" µS.");

  Serial.print("1° est égale à ");
  Serial.print(UsRange);
  Serial.println(" µS.");
  Serial.println();

}

void loop() {
  int PosDeg = Serial.parseInt(); // PosDeg = la position saisie dans le moniteur série de 0 à 173°
  float PosUs = LowerPos + (PosDeg * UsRange); // degré en µS
  if (Serial.available() > 0) {
    Serial.print(PosDeg);
    Serial.print("° = ");
    Serial.print(PosUs,2);
    Serial.println(" µS");

  }
    clearSerialBuffer();  
}

void clearSerialBuffer() {
  //clear serial buffer (but do nothing with it)
  while (Serial.available())
  {
    Serial.read();
  }
}
0
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
13 nov. 2019 à 19:03
Je n'ai pas d'Arduino, donc je ne peux pas le tester :(

Pour les soucis de précision, tu peux tester ceci ?
const byte ServoPin = 10;
const double LowerPos = 520 ; //Butée Mini du servo
const double UpperPos = 2480 ; //Butée Maxi du servo
const double Range = 173 ; //Plage de déplacement en degrés
const double T180 = LowerPos + ((UpperPos - LowerPos) / Range) * 180.0) ; //Extrapolation à 180° = 2559,306358381503
const double UsRange = (T180 - LowerPos) / 180.0;

0
NeriXs Messages postés 258 Date d'inscription lundi 4 mai 2015 Statut Membre Dernière intervention 27 février 2024 1
Modifié le 13 nov. 2019 à 20:00
Dois-je procéder de même pour les lignes 34 et 35 ?

Après test, J’obtiens exactement les mêmes résultats avec double qu’avec float.
0
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
14 nov. 2019 à 13:23
Je n'ai pas d'Arduino, j'ai essayé de faire un exemple en C/C++ pure.
En jouant sur le format du printf:
  • %f c'est pareil que %.2f, 2 après la virgule
  • %.10f veut dire 10 après la virgule.


Ça donne ceci:
#include <iostream>

int main() {
  const int LowerPos = 520 ; //Butée Mini du servo
  const int UpperPos = 2480 ; //Butée Maxi du servo
  const int Range = 173 ; //Plage de déplacement en degrés
  const double T180 = LowerPos + (((double)(UpperPos - LowerPos) / Range) * 180) ; //Extrapolation à 180° = 2559,306358381503
  const double UsRange = (T180 - LowerPos) / 180 ; // 1° = 11,32944444444444 µS

  printf("LowerPos: %d UpperPos: %d Range: %d T180: %.10f UsRange: %.10f\n", LowerPos, UpperPos, Range, T180, UsRange);
  for (int PosDeg = 0; PosDeg < 100; ++PosDeg) {
    double PosUs = LowerPos + (PosDeg * UsRange); // degré en µS
    printf("PosDeg: %d PosUs: %.10f\n", PosDeg, PosUs);
  }
  return 0;
}


Résultat affiché (une partie seulement):
LowerPos: 520 UpperPos: 2480 Range: 173 T180: 2559.3063583815 UsRange: 11.3294797688
PosDeg: 0 PosUs: 520.0000000000
PosDeg: 1 PosUs: 531.3294797688
PosDeg: 2 PosUs: 542.6589595376
PosDeg: 3 PosUs: 553.9884393064

0
NeriXs Messages postés 258 Date d'inscription lundi 4 mai 2015 Statut Membre Dernière intervention 27 février 2024 1
14 nov. 2019 à 19:51
Arduino ne semble pas aimer Printf et %.10f
Comment simplifier l’écriture pour vérifier cela ?
0
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
14 nov. 2019 à 20:04
On ne simplifie pas le langage, ça n'existe pas.
Si Arduino ne supporte pas entièrement le langage C ou C++, alors c'est un souci d'Arduino, pas de C/C++. Et il te faut poser ta question dans un forum Arduino.
0
NeriXs Messages postés 258 Date d'inscription lundi 4 mai 2015 Statut Membre Dernière intervention 27 février 2024 1
Modifié le 14 nov. 2019 à 20:44
0
NeriXs Messages postés 258 Date d'inscription lundi 4 mai 2015 Statut Membre Dernière intervention 27 février 2024 1
15 nov. 2019 à 18:17
Je pensais essayer la méthode donnée pour les "float" dans le lien du poste précédent en utilisant la fonction dtostrf().
Exemple :
    #define BUF_LEN 128 
    char buffer[BUF_LEN];
    char fBuffer[16];
    ....
     
      float fTemp = 25.45 ;
      dtostrf(fTemp,4,2,fBuffer); // largeur mimimale 4 ,  2 chiffres après la virgule
      snprintf(buffer,sizeof(buffer),"La température est %s °C\n\r",fBuffer  );
      Serial.print(buffer);


Mais, je ne sais pas comment calculer la taille du buffer adéquate à mon calcule.
Pouvez-vous m’aider ?
0
Rejoignez-nous