Arredondando o número para 2 casas decimais em C

Como posso arredondar um float (como 37.777779) para duas casas decimais (37.78) em C?

Se você quiser apenas arredondar o número para fins de saída, a string de formato "%.2f" é, de fato, a resposta correta. No entanto, se você realmente deseja arredondar o valor de ponto flutuante para computação adicional, algo como o seguinte funciona:

 #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 */ 

Observe que há três regras de arredondamento diferentes que você pode escolher: arredondar para baixo (ou seja, truncar após duas casas decimais), arredondado para o mais próximo e arredondar para cima. Normalmente, você quer arredondar para mais próximo.

Como vários outros apontaram, devido às peculiaridades da representação de ponto flutuante, esses valores arredondados podem não ser exatamente os valores decimais “óbvios”, mas eles estarão muito próximos.

Para muito (muito!) Mais informações sobre arredondamento e, especialmente, sobre regras de desempate para arredondamento para o mais próximo, consulte o artigo da Wikipedia sobre Arredondamento .

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

Supondo que você esteja falando sobre arredondar o valor para impressão, então a resposta de Andrew Coleson e AraK está correta:

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

Mas note que se você estiver com o objective de arredondar o número para exatamente 37,78 para uso interno (por exemplo, comparar com outro valor), então esta não é uma boa ideia, devido ao modo como os números de ponto flutuante funcionam: você normalmente não deseja fazer comparações de igualdade para ponto flutuante, em vez disso, use um valor de destino +/- um valor sigma. Ou codifique o número como uma string com uma precisão conhecida e compare isso.

Veja o link na resposta de Greg Hewgill para uma questão relacionada , que também aborda por que você não deve usar ponto flutuante para cálculos financeiros.

Que tal agora:

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

Se você quiser gravar em C-string:

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

Não existe uma maneira de arredondar um float para outro float porque o float arredondado pode não ser representável (uma limitação de números de ponto flutuante). Por exemplo, digamos que você arredonda 37,777779 para 37,78, mas o número representável mais próximo é 37,781.

No entanto, você pode “arredondar” um float usando uma function de string de formatação.

Além disso, se você estiver usando o C ++, você pode simplesmente criar uma function como esta:

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

Você pode então dar saída a qualquer double myDouble com n posições após o ponto decimal com código como este:

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

Você ainda pode usar:

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

exemplo:

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

Em C ++ (ou em C com conversões no estilo C), você poderia criar a function:

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

Então std::cout << showDecimals(37.777779,2); produziria: 37,78.

Obviamente você não precisa criar todas as 5 variables ​​nessa function, mas eu as deixo lá para que você possa ver a lógica. Existem provavelmente soluções mais simples, mas isso funciona bem para mim - especialmente porque me permite ajustar o número de dígitos após a casa decimal, conforme necessário.

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

Aqui n é o número de decimais

exemplo:

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

Use float roundf(float x) .

“A rodada funciona em torno de seu argumento para o valor inteiro mais próximo no formato de ponto flutuante, arredondando as checkboxs de meio caminho para longe de zero, independentemente da direção de arredondamento atual.” C11dr §7.12.9.5

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

Dependendo da sua implementação de float , números que podem parecer estar a meio caminho não são. como ponto flutuante é tipicamente orientado para base-2. Além disso, o arredondamento preciso para o 0.01 mais próximo em todos os casos “intermediários” é o mais desafiador.

 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 

Embora “1.115” esteja “a meio caminho” entre 1.11 e 1.12, quando convertido em float , o valor é 1.115000009537... e não está mais “a meio caminho”, mas próximo a 1.12 e arredonda para o próximo float de 1.120000004768...

“1.125” é “a meio caminho” entre 1.12 e 1.13, quando convertido para float , o valor é exatamente 1.125 e é “a meio caminho”. Ele gira em direção a 1.13 devido a empates até mesmo regra e arredonda para o float mais próximo de 1.129999995232...

Embora “1.135” esteja “a meio caminho” entre 1.13 e 1.14, quando convertido para float , o valor é 1.134999990463... e não está mais “a meio caminho”, mas mais próximo de 1.13 e arredonda para o float mais próximo de 1.129999995232...

Se o código usado

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

Embora “1.135” esteja “a meio caminho” entre 1.13 e 1.14, quando convertido para float , o valor é 1.134999990463... e não está mais “a meio caminho”, mas mais próximo de 1.13 mas incorretamente arredonda para float de 1.139999985695... devido à precisão mais limitada do float vs. Esse valor incorreto pode ser visto como correto, dependendo das metas de codificação.

Eu fiz essa macro para arredondar números de float. Adicione no seu header / sendo de arquivo

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

Aqui está um exemplo:

 float x = ROUNDF(3.141592, 100) 

x é igual a 3,14 🙂

Deixe-me primeiro tentar justificar minha razão para adicionar mais uma resposta a essa pergunta. Em um mundo ideal, o arredondamento não é realmente grande coisa. No entanto, em sistemas reais, pode ser necessário lidar com vários problemas que podem resultar em arredondamentos que podem não ser o esperado. Por exemplo, você pode estar realizando cálculos financeiros em que os resultados finais são arredondados e exibidos aos usuários com duas casas decimais; esses mesmos valores são armazenados com precisão fixa em um database que pode include mais de duas casas decimais (por vários motivos; não há número ideal de locais a serem mantidos … depende de situações específicas que cada sistema deve suportar, por exemplo, itens minúsculos são frações de um centavo por unidade); e, computações de ponto flutuante executadas em valores onde os resultados são mais / menos epsilon. Eu tenho confrontado essas questões e desenvolvido minha própria estratégia ao longo dos anos. Não vou alegar que enfrentei todos os cenários ou tenha a melhor resposta, mas abaixo está um exemplo da minha abordagem até o momento que supera essas questões:

Suponha que 6 casas decimais sejam consideradas como precisão suficiente para cálculos em floats / doubles (uma decisão arbitrária para a aplicação específica), usando a seguinte function / método de arredondamento:

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

O arredondamento para 2 casas decimais para apresentação de um resultado pode ser realizado como:

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

Para val = 6.825 , o resultado é 6.83 como esperado.

Para val = 6.824999 , o resultado é 6.82 . Aqui, a suposição é que o cálculo resultou exatamente em 6.824999 e a sétima casa decimal é zero.

Para val = 6.8249999 , o resultado é 6.83 . A 7ª casa decimal sendo 9 neste caso faz com que a function Round(val,6) forneça o resultado esperado. Para este caso, pode haver qualquer número de 9 s à direita.

Para val = 6.824999499999 , o resultado é 6.83 . Arredondar para a 8ª casa decimal como um primeiro passo, ou seja, Round(val,8) , cuida do caso desagradável pelo qual um resultado de ponto flutuante calculado é calculado para 6.8249995 , mas é representado internamente como 6.824999499999...

Finalmente, o exemplo da pergunta … val = 37.777779 resulta em 37.78 .

Essa abordagem poderia ser generalizada ainda mais como:

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

onde N é a precisão a ser mantida para todos os cálculos intermediários em floats / duplas. Isso funciona em valores negativos também. Eu não sei se essa abordagem é matematicamente correta para todas as possibilidades.

esta function pega o número e precisão e retorna o número arredondado

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

ele converte o número do ponto flutuante em int, deslocando o ponto para a esquerda e verificando a condição maior que cinco.

Tente este. Dará um double com duas casas decimais:

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