Nombre d’arrondi à 2 décimales en C

Comment puis-je arrondir un flottant (tel que 37.777779) à deux décimales (37.78) dans C?

Si vous voulez juste arrondir le nombre à des fins de sortie, la chaîne de format "%.2f" est en effet la bonne réponse. Cependant, si vous voulez arrondir la valeur en virgule flottante pour un calcul ultérieur, quelque chose comme les travaux suivants:

 #include  float val = 37.777779; float rounded_down = floorf(val * 100) / 100; /* Result: 37.77 */ float nearest = roundf(val * 100) / 100; /* Result: 37.78 */ float rounded_up = ceilf(val * 100) / 100; /* Result: 37.78 */ 

Notez que vous pouvez choisir trois règles d’arrondi: arrondi à la valeur la plus faible (arrondi après deux décimales), arrondi au plus proche et arrondi. Habituellement, vous voulez arrondir au plus près.

Comme plusieurs autres l’ont fait remarquer, en raison des bizarreries de la représentation en virgule flottante, ces valeurs arrondies peuvent ne pas être exactement les valeurs décimales “évidentes”, mais elles seront très très proches.

Pour plus (beaucoup!) D’informations sur l’arrondissement, et en particulier sur les règles d’arrondi pour arrondir au plus proche, consultez l’article de Wikipedia sur l’arrondi .

 printf("%.2f", 37.777779); 

En supposant que vous parlez de la valeur d’impression, Andrew Coleson et AraK répondent correctement:

 printf("%.2f", 37.777779); 

Mais notez que si vous souhaitez arrondir le nombre à exactement 37.78 pour un usage interne (par exemple pour comparer avec une autre valeur), ce n’est pas une bonne idée, à cause de la façon dont les nombres à virgule flottante fonctionnent. voulez faire des comparaisons d’égalité pour les virgules flottantes, utilisez plutôt une valeur cible +/- une valeur sigma. Ou encodez le nombre sous forme de chaîne avec une précision connue et comparez cela.

Voir le lien dans la réponse de Greg Hewgill à une question connexe , qui explique également pourquoi vous ne devriez pas utiliser de virgule flottante pour les calculs financiers.

Que dis-tu de ça:

 float value = 37.777779; float rounded = ((int)(value * 100 + .5) / 100.0); 
 printf("%.2f", 37.777779); 

Si vous voulez écrire dans une chaîne de caractères:

 char number[24]; // dummy size, you should take care of the size! sprintf(number, "%.2f", 37.777779); 

Il n’y a pas moyen d’arrondir un float à un autre float car le float arrondi peut ne pas être représentable (une limitation des nombres à virgule flottante). Par exemple, disons que vous arrondissez 37,777779 à 37,78, mais que le nombre représentable le plus proche est 37,781.

Cependant, vous pouvez “arrondir” un float en utilisant une fonction de chaîne de format.

De plus, si vous utilisez C ++, vous pouvez simplement créer une fonction comme celle-ci:

 ssortingng prd(const double x, const int decDigits) { ssortingngstream ss; ss < < fixed; ss.precision(decDigits); // set # places after decimal ss << x; return ss.str(); } 

Vous pouvez ensuite afficher n'importe quel double myDouble avec n lieux après le point décimal avec un code tel que celui-ci:

 std::cout < < prd(myDouble,n); 

Vous pouvez toujours utiliser:

 float ceilf(float x); // don't forget #include  and link with -lm. 

Exemple:

 float valueToRound = 37.777779; float roundedValue = ceilf(valueToRound * 100) / 100; 

En C ++ (ou en C avec des moulages de style C), vous pouvez créer la fonction:

 /* Function to control # of decimal places to be output for x */ double showDecimals(const double& x, const int& numDecimals) { int y=x; double z=xy; double m=pow(10,numDecimals); double q=z*m; double r=round(q); return static_cast(y)+(1.0/m)*r; } 

Puis std::cout < < showDecimals(37.777779,2); produirait: 37,78.

De toute évidence, vous n'avez pas vraiment besoin de créer les 5 variables dans cette fonction, mais je les laisse là pour que vous puissiez voir la logique. Il y a probablement des solutions plus simples, mais cela fonctionne bien pour moi - d'autant plus que cela me permet d'ajuster le nombre de chiffres après la décimale selon mes besoins.

 double f_round(double dval, int n) { char l_fmtp[32], l_buf[64]; char *p_str; sprintf (l_fmtp, "%%.%df", n); if (dval>=0) sprintf (l_buf, l_fmtp, dval); else sprintf (l_buf, l_fmtp, dval); return ((double)strtod(l_buf, &p_str)); } 

Ici n est le nombre de décimales

Exemple:

 double d = 100.23456; printf("%f", f_round(d, 4));// result: 100.2346 printf("%f", f_round(d, 2));// result: 100.23 

Utilisez float roundf(float x) .

“Les fonctions rondes arrondissent leur argument à la valeur entière la plus proche au format à virgule flottante, en arrondissant à mi-course à zéro, indépendamment de la direction d’arrondissement actuelle.” C11dr §7.12.9.5

 #include  float y = roundf(x * 100.0f) / 100.0f; 

Selon l’implémentation de votre float , les nombres qui semblent être à mi-chemin ne le sont pas. comme virgule flottante est généralement orienté base 2. En outre, l’arrondissement précis à 0.01 près sur tous les cas “à mi-chemin” est le plus difficile.

 void r100(const char *s) { float x, y; sscanf(s, "%f", &x); y = round(x*100.0)/100.0; printf("%6s %.12e %.12e\n", s, x, y); } int main(void) { r100("1.115"); r100("1.125"); r100("1.135"); return 0; } 1.115 1.115000009537e+00 1.120000004768e+00 1.125 1.125000000000e+00 1.129999995232e+00 1.135 1.134999990463e+00 1.139999985695e+00 

Bien que “1.115” soit “à mi-chemin” entre 1.11 et 1.12, converti en float , la valeur est 1.115000009537... et n’est plus “à mi-chemin”, mais plus proche de 1.12 et arrondit au float le plus proche de 1.120000004768...

“1.125” est “à mi-chemin” entre 1.12 et 1.13, quand converti en valeur float , la valeur est exactement 1.125 et est “à mi-chemin”. Il arrondit vers 1.13 en raison des égalités à égaliser et arrondit au float le plus proche de 1.129999995232...

Bien que “1.135” soit “à mi-chemin” entre 1.13 et 1.14, une fois converti en float , la valeur est 1.134999990463... et n’est plus “à mi-chemin”, mais plus proche de 1.13 et 1.129999995232...

Si code utilisé

 y = roundf(x*100.0f)/100.0f; 

Bien que “1.135” soit “à mi-chemin” entre 1.13 et 1.14, une fois converti en float , la valeur est 1.134999990463... et n’est plus “à mi-chemin”, mais plus proche de 1.13 mais 1.139999985695... raison de la précision plus limitée du float vs double . Cette valeur incorrecte peut être considérée comme correcte, en fonction des objectives de codage.

J’ai fait cette macro pour arrondir les nombres flottants. Ajoutez-le dans votre en-tête / être du fichier

 #define ROUNDF(f, c) (((float)((int)((f) * (c))) / (c))) 

Voici un exemple:

 float x = ROUNDF(3.141592, 100) 

x est égal à 3,14 🙂

Laissez-moi d’abord essayer de justifier ma raison pour append encore une autre réponse à cette question. Dans un monde idéal, l’arrondissement n’est pas vraiment une grosse affaire. Cependant, dans les systèmes réels, vous devrez peut-être faire face à plusieurs problèmes qui peuvent entraîner l’arrondi, ce qui n’est peut-être pas ce que vous attendez. Par exemple, vous pouvez effectuer des calculs financiers où les résultats finaux sont arrondis et affichés pour les utilisateurs sous forme de 2 décimales; ces mêmes valeurs sont stockées avec une précision fixe dans une firebase database pouvant comprendre plus de 2 décimales (pour diverses raisons, il n’y a pas de nombre optimal de lieux à conserver … dépend des situations spécifiques que chaque système doit prendre en charge, par exemple sont des fractions de cent par unité); et des calculs en virgule flottante effectués sur des valeurs dont les résultats sont plus / moins epsilon. J’ai été confronté à ces problèmes et développé ma propre stratégie au fil des ans. Je ne prétends pas avoir affronté tous les scénarios ou avoir la meilleure réponse, mais voici un exemple de mon approche jusqu’ici qui résout ces problèmes:

Supposons que 6 décimales soient considérées comme une précision suffisante pour les calculs sur floats / doubles (une décision arbitraire pour l’application spécifique), en utilisant la fonction / méthode d’arrondi suivante:

 double Round(double x, int p) { if (x != 0.0) { return ((floor((fabs(x)*pow(double(10.0),p))+0.5))/pow(double(10.0),p))*(x/fabs(x)); } else { return 0.0; } } 

L’arrondi à 2 décimales pour la présentation d’un résultat peut être effectué comme suit:

 double val; // ...perform calculations on val Ssortingng(Round(Round(Round(val,8),6),2)); 

Pour val = 6.825 , le résultat est 6.83 comme prévu.

Pour val = 6.824999 , le résultat est 6.82 . Ici, l’hypothèse est que le calcul a abouti exactement à 6.824999 et que la 7ème décimale est zéro.

Pour val = 6.8249999 , le résultat est 6.83 . La 7ème décimale étant 9 dans ce cas, la fonction Round(val,6) donne le résultat attendu. Dans ce cas, il pourrait y avoir un nombre quelconque de 9 secondes.

Pour val = 6.824999499999 , le résultat est 6.83 . Arrondir à la 8ème décimale en premier lieu, c.-à-d. Round(val,8) , prend en compte le seul cas grave dans lequel un résultat calculé en virgule flottante est calculé à 6.8249995 , mais est représenté en interne par 6.824999499999... .

Enfin, l’exemple de la question … val = 37.777779 donne val = 37.777779 .

Cette approche pourrait être encore généralisée comme suit:

 double val; // ...perform calculations on val Ssortingng(Round(Round(Round(val,N+2),N),2)); 

où N est la précision à conserver pour tous les calculs intermédiaires sur les flottants / doubles. Cela fonctionne également sur les valeurs négatives. Je ne sais pas si cette approche est mathématiquement correcte pour toutes les possibilités.

cette fonction prend le nombre et la précision et retourne le nombre arrondi

 float roundoff(float num,int precision) { int temp=(int )(num*pow(10,precision)); int num1=num*pow(10,precision+1); temp*=10; temp+=5; if(num1>=temp) num1+=10; num1/=10; num1*=10; num=num1/pow(10,precision+1); return num; } 

il convertit le nombre à virgule flottante en int en déplaçant le point à gauche et en vérifiant la condition supérieure à cinq.

Essaye celui-là. Il donnera un double avec deux décimales:

 int ttt = round(value * 100); ssortingng str = to_ssortingng(ttt); str.insert (str.end()-2,1,'.'); double temp = ::strtod(str.c_str(), 0); obPrinciple = temp;