El estándar C ++ 03 se basa en el estándar C90 para lo que el estándar llama la Biblioteca de C estándar que se cubre en el borrador del estándar C ++ 03 (el borrador de estándar disponible públicamente más cercano a C ++ 03 es N1804 ) sección 1.2
Referencias normativas :
La biblioteca descrita en la cláusula 7 de ISO / IEC 9899: 1990 y la cláusula 7 de ISO / IEC 9899 / Amd.1: 1995 se denomina en adelante Biblioteca estándar C. 1)
Si vamos a la documentación de C para round, lround, llround en cppreference , podemos ver que round y las funciones relacionadas son parte de C99 y, por lo tanto, no estarán disponibles en C ++ 03 o anteriores.
En C ++ 11 esto cambia ya que C ++ 11 se basa en el borrador del estándar C99 para la biblioteca estándar C y, por lo tanto, proporciona std :: round y para los 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 ;
}
Otra opción también de C99 sería std :: trunc que:
Calcula el entero más cercano no mayor en magnitud 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 ;
}
Si necesita admitir aplicaciones que no sean C ++ 11, su mejor opción sería utilizar boost round, iround, lround, llround o boost trunc .
Rodar tu propia versión de round es difícil
Rodar el tuyo probablemente no valga la pena ya que es más difícil de lo que parece: redondear el flotador al entero más cercano, parte 1 , Redondear el flotador al entero más cercano, parte 2 y Redondear el flotador al entero más cercano, parte 3 explica:
Por ejemplo, un rol común que su implementación usa std::floor
y agrega 0.5
no funciona para todas las entradas:
double myround(double d)
{
return std::floor(d + 0.5);
}
Una entrada por la que fallará es 0.49999999999999994
( ver en vivo ).
Otra implementación común implica convertir un tipo de punto flotante a un tipo integral, que puede invocar un comportamiento indefinido en el caso en que la parte integral no se pueda representar en el tipo de destino. Podemos ver esto en el borrador de la sección estándar de C ++ 4.9
Conversiones flotantes integrales que dice ( énfasis mío ):
Un prvalue de un tipo de coma flotante se puede convertir en un prvalue de un tipo entero. La conversión se trunca; es decir, la parte fraccionaria se descarta. El comportamiento no está definido si el valor truncado no se puede representar en el tipo de destino. [...]
Por ejemplo:
float myround(float f)
{
return static_cast<float>( static_cast<unsigned int>( f ) ) ;
}
Teniendo en cuenta std::numeric_limits<unsigned int>::max()
es 4294967295
entonces la siguiente llamada:
myround( 4294967296.5f )
causará desbordamiento ( véalo en vivo ).
Podemos ver cuán difícil es realmente esto al ver esta respuesta a la forma concisa de implementar round () en C? que hace referencia a la versión newlibs de ronda flotante de precisión simple. Es una función muy larga para algo que parece simple. Parece poco probable que alguien sin un conocimiento profundo de las implementaciones de coma flotante pueda implementar correctamente esta función:
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 otro lado, si ninguna de las otras soluciones son utilizables, newlib podría ser una opción, ya que es una implementación bien probada.
std::cout << std::fixed << std::setprecision(0) << -0.9
, por ejemplo.