Existe uma função para arredondar um float em C ou que eu preciso para escrever a minha própria?

StackOverflow https://stackoverflow.com/questions/497018

  •  20-08-2019
  •  | 
  •  

Pergunta

Existe uma função para arredondar um float em C ou eu preciso escrever meu próprio?

flutuador conver = 45. 59 2346543;

Gostaria de arredondar o valor real de uma casa decimal, conver = 45. 6 .

Foi útil?

Solução

Como Rob mencionado, você provavelmente só quero print o flutuador 1 casa decimal. Neste caso, você pode fazer algo como o seguinte:

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

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

Se você quiser realmente arredondar o valor armazenado, que é um pouco mais complicado. Por um lado, a sua representação de uma casa decimal raramente têm um análogo exato em ponto flutuante. Se você só quer ficar o mais próximo possível, algo como isso poderia fazer o truque:

#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;
}

Eu duvido que este segundo exemplo é o que você está procurando, mas eu incluí-lo por completo. Se você exigem representando os números desta forma internamente, e não apenas na saída, considere usar um fixo representação de ponto vez.

Outras dicas

Claro, você pode usar roundf () . Se você quiser rodada para uma casa decimal, então você poderia fazer algo como: roundf(10 * x) / 10

#include <math.h>

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

Não se esqueça de ligação com -lm. Veja também ceil (), floor () e trunc ().

Apenas generalizar a resposta de Rob um pouco, se você estiver não fazê-lo na saída, você ainda pode usar a mesma interface com sprintf().

Eu acho que não há outra maneira de fazê-lo, no entanto. Você pode tentar ceil() e floor() para cima rodada e para baixo. Um bom truque é adicionar 0,5, então qualquer coisa mais de 0,5 rodadas para cima, mas nada sob ele arredonda para baixo. ceil() e floor() único trabalho em doubles embora.

EDIT: Além disso, para floats, você pode usar truncf() para carros alegóricos truncamento. O mesmo +0.5 truque deve trabalhar para fazer o arredondamento preciso.

Há uma função round(), também fround(), que volta para o número inteiro mais próximo, expresso em dupla. Mas isso não é o que você quer.

Eu tive o mesmo problema e escreveu o seguinte:

#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;
} 

Para print um valor arredondado, @ Matt J bem responde à pergunta.

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

ponto Como a maioria flutuante (FP) é binário com base, exata arredondamento a um decimal lugar não é possível quando a resposta matematicamente correta é x.1, x.2, ....

Para converter o número FP ao mais próximo 0.1 é outra questão.

Overflow :. Abordagens que a primeira escala de 10 (ou 100, 1000, etc.) pode transbordar para grande x

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

Duplo arredondamento :. Adicionando 0.5f e em seguida, usando floorf(x*10.0f + 0.5f)/10.0 retorna o resultado errado quando os intermediários soma x*10.0f + 0.5f rodadas até um novo inteiro

// 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;
}

Fundição para int tem o problema óbvio quando float x é muito maior do que INT_MAX.


Usando roundf() e familiar, disponível em <math.h> é a melhor abordagem.

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

Para evitar o uso double, simplesmente testar se o número precisa de arredondamento.

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;
}

Você pode usar #define rodada (a) (int) (a + 0,5) como macro Assim, sempre que você escreve rodada (1,6) retorna 2 e sempre que você escrever round (1.3) que retornar 1.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top