O C ++ 03 norma baseia-se no padrão C90 para o que as chamadas padrão do C biblioteca padrão que é coberto no projecto C ++ 03 padrão ( mais próxima disponível publicamente projecto de norma para C ++ 03 é N1804 ) seção 1.2
Referências normativas :
A biblioteca descrita na cláusula 7 da ISO / IEC 9899: 1990 e cláusula 7 da ISO / IEC 9899 / Amd.1: 1995 é a seguir denominada Biblioteca C Padrão. 1)
Se formos à documentação C para round, lround, llround na cppreference , podemos ver que as funções round e relacionadas fazem parte do C99 e, portanto, não estarão disponíveis no C ++ 03 ou anterior.
No C ++ 11, isso muda, pois o C ++ 11 depende do padrão de rascunho C99 da biblioteca padrão C e, portanto, fornece std :: round e para os tipos de retorno integral std :: lround, std :: llround :
#include <iostream>
#include <cmath>
int main()
{
std::cout << std::round( 0.4 ) << " " << std::lround( 0.4 ) << " " << std::llround( 0.4 ) << std::endl ;
std::cout << std::round( 0.5 ) << " " << std::lround( 0.5 ) << " " << std::llround( 0.5 ) << std::endl ;
std::cout << std::round( 0.6 ) << " " << std::lround( 0.6 ) << " " << std::llround( 0.6 ) << std::endl ;
}
Outra opção também do C99 seria std :: trunc, que:
Calcula o número inteiro mais próximo não maior em magnitude que arg.
#include <iostream>
#include <cmath>
int main()
{
std::cout << std::trunc( 0.4 ) << std::endl ;
std::cout << std::trunc( 0.9 ) << std::endl ;
std::cout << std::trunc( 1.1 ) << std::endl ;
}
Se você precisa para apoiar non C ++ 11 aplicações a sua melhor aposta seria usar boost rodada, iround, lround, llround ou impulso trunc .
Rodar sua própria versão da rodada é difícil
Rolar o seu próprio provavelmente não vale o esforço, pois é mais difícil do que parece: arredondar a flutuação para o número inteiro mais próximo, parte 1 , arredondar a flutuação para o número inteiro mais próximo, parte 2 e Arredondar a flutuação para o número inteiro mais próximo, parte 3 explica:
Por exemplo, um teste comum de sua implementação usando std::floor
e adicionando 0.5
não funciona para todas as entradas:
double myround(double d)
{
return std::floor(d + 0.5);
}
Uma entrada pela qual falhará é 0.49999999999999994
( veja ao vivo ).
Outra implementação comum envolve converter um tipo de ponto flutuante para um tipo integral, que pode chamar um comportamento indefinido no caso em que a parte integral não pode ser representada no tipo de destino. Podemos ver isso no rascunho da seção padrão do C ++ 4.9
Conversões integrais flutuantes que diz ( ênfase minha ):
Um pré-valor de um tipo de ponto flutuante pode ser convertido em um pré-valor de um tipo inteiro. A conversão trunca; isto é, a parte fracionária é descartada. O comportamento é indefinido se o valor truncado não puder ser representado no tipo de destino. [...]
Por exemplo:
float myround(float f)
{
return static_cast<float>( static_cast<unsigned int>( f ) ) ;
}
Dado std::numeric_limits<unsigned int>::max()
é 4294967295
então a seguinte chamada:
myround( 4294967296.5f )
causará estouro ( veja ao vivo ).
Podemos ver o quão difícil isso realmente é, olhando para esta resposta da maneira Concisa de implementar round () em C? que faz referência à versão newlibs da precisão única flutuante. É uma função muito longa para algo que parece simples. Parece improvável que qualquer pessoa sem conhecimento íntimo das implementações de ponto flutuante possa implementar corretamente esta função:
float roundf(x)
{
int signbit;
__uint32_t w;
/* Most significant word, least significant word. */
int exponent_less_127;
GET_FLOAT_WORD(w, x);
/* Extract sign bit. */
signbit = w & 0x80000000;
/* Extract exponent field. */
exponent_less_127 = (int)((w & 0x7f800000) >> 23) - 127;
if (exponent_less_127 < 23)
{
if (exponent_less_127 < 0)
{
w &= 0x80000000;
if (exponent_less_127 == -1)
/* Result is +1.0 or -1.0. */
w |= ((__uint32_t)127 << 23);
}
else
{
unsigned int exponent_mask = 0x007fffff >> exponent_less_127;
if ((w & exponent_mask) == 0)
/* x has an integral value. */
return x;
w += 0x00400000 >> exponent_less_127;
w &= ~exponent_mask;
}
}
else
{
if (exponent_less_127 == 128)
/* x is NaN or infinite. */
return x + x;
else
return x;
}
SET_FLOAT_WORD(x, w);
return x;
}
Por outro lado, se nenhuma das outras soluções for utilizável, newlib pode ser uma opção, pois é uma implementação bem testada.
std::cout << std::fixed << std::setprecision(0) << -0.9
, por exemplo.