web-dev-qa-db-fra.com

Existe-t-il une fonction pour arrondir un nombre dans C ou dois-je écrire le mien?

Existe-t-il une fonction pour arrondir un nombre dans C ou dois-je écrire le mien? 

float conver = 45. 59 2346543;

Je voudrais arrondir la valeur réelle à une décimale, conver = 45. 6 .

23
T.T.T.

Comme Rob l'a mentionné, vous voulez probablement juste imprimer le flottant à 1 décimale. Dans ce cas, vous pouvez effectuer les opérations suivantes:

#include <stdio.h>
#include <stdlib.h>

int main()
{
  float conver = 45.592346543;
  printf("conver is %0.1f\n",conver);
  return 0;
}

Si vous voulez réellement arrondir la valeur stockée, c'est un peu plus compliqué. D'une part, votre représentation à une décimale aura rarement un analogue exact en virgule flottante. Si vous voulez juste vous rapprocher le plus possible, une chose comme celle-ci pourrait faire l'affaire:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main()
{
  float conver = 45.592346543;
  printf("conver is %0.1f\n",conver);

  conver = conver*10.0f;
  conver = (conver > (floor(conver)+0.5f)) ? ceil(conver) : floor(conver);
  conver = conver/10.0f;

  //If you're using C99 or better, rather than ANSI C/C89/C90, the following will also work.
  //conver = roundf(conver*10.0f)/10.0f;

  printf("conver is now %f\n",conver);
  return 0;
}

Je doute que ce second exemple correspond à ce que vous recherchez, mais je l’ai inclus pour plus de précision. Si vous avez besoin de représenter vos nombres de cette manière en interne, et pas seulement en sortie, utilisez plutôt une représentation en virgule fixe .

28
Matt J

Bien sûr, vous pouvez utiliser roundf () . Si vous voulez arrondir à une décimale, vous pouvez faire quelque chose comme: roundf(10 * x) / 10

28

Pour imprimer une valeur arrondie, @Matt J well répond à la question.

float x = 45.592346543;
printf("%0.1f\n", x);  // 45.6

Comme la plupart des virgules flottantes (FP) sont basées sur binaire _, exact arrondir à un décimal n'est pas possible lorsque la réponse mathématiquement correcte est x.1, x.2, ....

Convertir le nombre FP en le plus proche0.1 est une autre affaire.

Overflow: les premières échelles de 10 (ou 100, 1000, etc.) risquent de déborder pour une grande variable x.

float round_tenth1(float x) {
  x = x * 10.0f;
  ...
}

Double arrondi: l'ajout de 0.5f, puis l'utilisation de floorf(x*10.0f + 0.5f)/10.0 renvoie un résultat incorrect lorsque la somme intermédiaire x*10.0f + 0.5f est arrondie à un nouvel entier.

// Fails to round 838860.4375 correctly, comes up with 838860.5 
// 0.4499999880790710449 fails as it rounds to 0.5
float round_tenth2(float x) {
  if (x < 0.0) {
    return ceilf(x*10.0f + 0.5f)/10.0f;
  }
  return floorf(x*10.0f + 0.5f)/10.0f;
}

Casting to int a le problème évident quand float x est beaucoup plus grand que INT_MAX.


Utiliser roundf() et la famille, disponible dans <math.h> est la meilleure approche.

float round_tenthA(float x) {
  double x10 = 10.0 * x;
  return (float) (round(x10)/10.0);
}

Pour éviter d'utiliser double, testez simplement si le nombre doit être arrondi.

float round_tenthB(float x) {
  const float limit = 1.0/FLT_EPSILON;
  if (fabsf(x) < limit) {
    return roundf(x*10.0f)/10.0f;
  }
  return x;
}
1
chux

Il existe une fonction round(), également fround(), qui arrondira au nombre entier le plus proche exprimé en double. Mais ce n'est pas ce que tu veux. 

J'ai eu le même problème et a écrit ceci:

#include <math.h>

   double db_round(double value, int nsig)
/* ===============
**
** Rounds double <value> to <nsig> significant figures.  Always rounds
** away from zero, so -2.6 to 1 sig fig will become -3.0.
**
** <nsig> should be in the range 1 - 15
*/

{
    double     a, b;
    long long  i;
    int        neg = 0;


    if(!value) return value;

    if(value < 0.0)
    {
        value = -value;
        neg = 1;
    }

    i = nsig - log10(value);

    if(i) a = pow(10.0, (double)i);
    else  a = 1.0;

    b = value * a;
    i = b + 0.5;
    value = i / a;

    return neg ? -value : value;
} 
1
Christopher Bel
#include <math.h>

double round(double x);
float roundf(float x);

N'oubliez pas de vous connecter avec -lm. Voir aussi ceil (), floor () et trunc ().

1
Joao da Silva

Juste pour généraliser un peu la réponse de Rob, si vous pas le faites en sortie, vous pouvez toujours utiliser la même interface avec sprintf().

Je pense qu'il y a une autre façon de le faire, cependant. Vous pouvez essayer ceil() et floor() pour arrondir de haut en bas. Une bonne astuce consiste à ajouter 0,5, donc tout ce qui dépasse 0,5 arrondit mais tout ce qui est en dessous arrondit vers le bas. ceil() et floor() ne fonctionnent que sur doubles.

EDIT: De plus, pour les floats, vous pouvez utiliser truncf() pour les tronquer. La même astuce +0,5 devrait permettre d’arrondir avec précision.

1
Chris Lutz

vous pouvez utiliser #define round (a) (int) (a + 0.5) comme macro ainsi, chaque fois que vous écrivez le tour (1.6), il retourne 2 et chaque fois que vous écrivez le tour (1.3), il retourne 1.

0
redblood