Obtenir un float parfait ...

Bonjour à tous chers programmeurs ! 8)

Je viens à vous aujourd'hui car j'ai créé une fonction me permettant d'«arrondir» des nombres à virgule flottante (float) seulement, l'arrondi n'est pas parfait. Voici un exemple:

Lorsque je fais roundFloat(48.457698746), je voudrais que la fonction me retourne seulement 48.4576. Soit seulement 4 chiffres après la virgule, le reste étant des 0.

Pour se faire, voici la fonction que j'ai créé:

float roundFloat(float value) {
  float f1 = (value*10000);
  String s1 = String(f1);
  long i1 = s1.toInt();
  float f2 = float(i1) / 10000;
  return f2;
}

Seulement, lorsque j'affiche la valeur en retour, j'obtiens divers arrondis selon si je demande au moniteur série d'afficher 3, 4 ou 6 chiffres après la virgule. Je voudrais faire en sorte d'obtenir 48.45760000 pile! Peu importe combien de nombres après la virgule on veut afficher.

Merci d'avoir lu et pour votre aide ! :slight_smile:
Si vous avez des questions, n'hésitez pas :wink:

Bonjour,

Est-ce que tu te rends compte que si le nombre d'origine est 48.457698746 et que tu affiches 48.45760000, c'est faux ?

Tu n'as que deux solutions: ou bien tu affiches 48.457698746, ou bien tu affiches 48.4576, mais afficher 48.45760000 ça n'a aucun sens.

Bonjour,

Ce que tu veux faire est impossible. Cela tient au format des float qui sont des puissances de base 2 alors que tu raisonnes en base 10. Voir Virgule flottante

3Sigma:
Bonjour,

Est-ce que tu te rends compte que si le nombre d'origine est 48.457698746 et que tu affiches 48.45760000, c'est faux ?

Tu n'as que deux solutions: ou bien tu affiches 48.457698746, ou bien tu affiches 48.4576, mais afficher 48.45760000 ça n'a aucun sens.

kamill:
Bonjour,

Ce que tu veux faire est impossible. Cela tient au format des float qui sont des puissances de base 2 alors que tu raisonnes en base 10. Voir Virgule flottante

Merci pour vos réponses ! Oui en effet, vous m'avez fait réaliser que ce n'était pas cohérent. Merci :slight_smile:
Je vais faire autrement :wink:

pepe:
Bonsoir

Ce n'est simplement pas possible.

Un float représente un nombre à virgule flottante en base 2, et non pas en base 10.

L'arrondi d'un float à une puissance entière négative de 10 a toutes les chances d'être le résultat d'une division entière de 5. Or, en base 2 la division par 5 est susceptible de donner un résultat présentant un nombre infini de chiffres après la virgule (1/5 = 0,001100110011...), d'une façon similaire à la division par 3 en base 10 (1/3 = 0,3333333...). Un float présentant forcément un nombre fini de bits, cet arrondi décimal risque d'être à son tour arrondi à une valeur différente au moment du stockage.

Par exemple la valeur 48,4576 sera stockée sous la forme :

(-1)0x1.10000011101010010010101x2(10000100-01111111) (les bits colorés sont ceux effectivement stockés dans le float)

qui vaut environ 48,45759963989258 en base 10.

Si l'on ne veut pas que les nombres soient modifiés lors des conversions entre la base 2 (stockage et calcul) et la base 10 (saisie et affichage), il faut s'en tenir à l'utilisation de nombres entiers, ce qu'on peut faire en modifiant les unités des grandeurs considérées.

Par exemple, pour garder les quatre chiffres décimaux après la virgule de 48,4576 , il faut considérer qu'il s'agit de 484576 unités entières de 1/10000ème.

Un énorme merci à toi @pepe ! Ton explication était vraiment claire, elle m'a permis d'ouvrir les yeux :slight_smile:
Encore merci pour tout vos conseils ! Je sais ce qu'il me reste à faire maintenant, nickel :wink:

Attention également, si tu veux obtenir 48.4576 à partir de 48.457698746, cela s'appelle tronquer et non arrondir. L'arrondi de 48.457698746 c'est 48.4577 (la cinquième décimale étant supérieur ou égale à 5)