[C++] Type entier vers flottant. [Résolu]

Messages postés
115
Date d'inscription
lundi 4 mai 2015
Statut
Membre
Dernière intervention
15 novembre 2019
-
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.
Afficher la suite 

20/21 réponses

Messages postés
14597
Date d'inscription
vendredi 14 mars 2003
Statut
Modérateur
Dernière intervention
2 décembre 2019
137
0
Merci
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.
Commenter la réponse de NHenry
Messages postés
115
Date d'inscription
lundi 4 mai 2015
Statut
Membre
Dernière intervention
15 novembre 2019
0
Merci
J’avoue être un peu largué, auriez-vous un petit exemple concret ?
Commenter la réponse de NeriXs
Messages postés
3801
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
15 novembre 2019
90
0
Merci
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



Améliorer votre expérience CodeS-SourceS avec ce plugin:
http://codes-sources.commentcamarche.net/forum/affich-10000111-plugin-better-cs-2#cptpingu-signature
Commenter la réponse de cptpingu
Messages postés
115
Date d'inscription
lundi 4 mai 2015
Statut
Membre
Dernière intervention
15 novembre 2019
0
Merci
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
Commenter la réponse de NeriXs
Messages postés
3801
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
15 novembre 2019
90
0
Merci
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).
Commenter la réponse de cptpingu
Messages postés
115
Date d'inscription
lundi 4 mai 2015
Statut
Membre
Dernière intervention
15 novembre 2019
0
Merci
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?
Commenter la réponse de NeriXs
Messages postés
3801
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
15 novembre 2019
90
0
Merci
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 ?
Commenter la réponse de cptpingu
Messages postés
115
Date d'inscription
lundi 4 mai 2015
Statut
Membre
Dernière intervention
15 novembre 2019
0
Merci
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!
Commenter la réponse de NeriXs
Messages postés
3801
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
15 novembre 2019
90
0
Merci
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.
Commenter la réponse de cptpingu
Messages postés
115
Date d'inscription
lundi 4 mai 2015
Statut
Membre
Dernière intervention
15 novembre 2019
0
Merci
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
Commenter la réponse de NeriXs
Messages postés
3801
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
15 novembre 2019
90
0
Merci
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...
Commenter la réponse de cptpingu
Messages postés
115
Date d'inscription
lundi 4 mai 2015
Statut
Membre
Dernière intervention
15 novembre 2019
0
Merci
Le code est en poste 4.
Commenter la réponse de NeriXs
Messages postés
115
Date d'inscription
lundi 4 mai 2015
Statut
Membre
Dernière intervention
15 novembre 2019
0
Merci
@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();
  }
}
Commenter la réponse de NeriXs
Messages postés
3801
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
15 novembre 2019
90
0
Merci
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;

Commenter la réponse de cptpingu
Messages postés
115
Date d'inscription
lundi 4 mai 2015
Statut
Membre
Dernière intervention
15 novembre 2019
0
Merci
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.
Commenter la réponse de NeriXs
Messages postés
3801
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
15 novembre 2019
90
0
Merci
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

Commenter la réponse de cptpingu
Messages postés
115
Date d'inscription
lundi 4 mai 2015
Statut
Membre
Dernière intervention
15 novembre 2019
0
Merci
Arduino ne semble pas aimer Printf et %.10f
Comment simplifier l’écriture pour vérifier cela ?
Commenter la réponse de NeriXs
Messages postés
3801
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
15 novembre 2019
90
0
Merci
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.
Commenter la réponse de cptpingu
Messages postés
115
Date d'inscription
lundi 4 mai 2015
Statut
Membre
Dernière intervention
15 novembre 2019
0
Merci
Une solution peut être ici:
http://arlotto.univ-tln.fr/arduino/article/arduino-printf
Commenter la réponse de NeriXs
Messages postés
115
Date d'inscription
lundi 4 mai 2015
Statut
Membre
Dernière intervention
15 novembre 2019
0
Merci
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 ?
Commenter la réponse de NeriXs