Las diferencias residen en el valor devuelto que proporciona entradas sobre el desempate, creo, como este código :
int main()
{
std::cout.precision(100);
double input = std::nextafter(0.05, 0.0) / 0.1;
double x1 = floor(0.5 + input);
double x2 = round(input);
std::cout << x1 << std::endl;
std::cout << x2 << std::endl;
}
que salidas:
1
0
Pero son solo resultados diferentes al final, uno elige su preferido. Veo muchos programas "antiguos" de C / C ++ que usan en floor(0.5 + input)
lugar de round(input)
.
¿Existe alguna razón histórica? ¿Más barato en la CPU?
Respuestas:
std::round
se introduce en C ++ 11. Antes de eso, solostd::floor
estaba disponible para que los programadores lo estuvieran usando.fuente
No hay ninguna razón histórica. Este tipo de desviación ha existido desde el año punto. La gente hace esto cuando se siente muy, muy traviesa. Es un abuso de la aritmética de coma flotante, y muchos programadores profesionales experimentados caen en la trampa. Incluso los cuerpos de Java lo hicieron hasta la versión 1.7. Chicos divertidos.
Mi conjetura es que una función de redondeo alemana decente y lista para usar no estuvo disponible formalmente hasta C ++ 11 (a pesar de que C obtuvo la suya en C99), pero eso realmente no es excusa para adoptar la supuesta alternativa.
Aquí está la cuestión:
floor(0.5 + input)
no siempre recupera el mismo resultado que el correspondientestd::round
llamada !La razón es bastante sutil: el punto de corte para un redondeo alemán,
a.5
para un enteroa
, es, por una propiedad coincidente del universo, un racional diádico . Como esto se puede representar exactamente en un punto flotante IEEE754 hasta la potencia 52 de 2, y a partir de entonces el redondeo es una operación no válida de todos modos,std::round
siempre funciona correctamente. Para otros esquemas de coma flotante, consulte la documentación.Pero agregar
0.5
a unadouble
lata introduce imprecisión, lo que provoca un ligero sobrepaso o subestimado de algunos valores. Si lo piensa, sumar dosdouble
valores juntos, que son el comienzo de conversiones denarias involuntarias, y aplicar una función que es una función muy fuerte de la entrada (como una función de redondeo), seguramente terminará en lágrimas.No lo hagas .
Referencia: ¿Por qué Math.round (0.49999999999999994) devuelve 1?
fuente
nearbyint()
suele ser una mejor opción queround()
, porquenearbyint
usa el modo de redondeo actual en lugar del funky tiebreak lejos de cero deround()
(para el cual x86 ni siquiera tiene soporte de hardware, aunque ARM sí). Ambos se agregaron a C ++ en C ++ 11.Creo que aquí es donde te equivocas:
Ese no es el caso. Debe seleccionar el esquema de redondeo correcto para el dominio . En una aplicación financiera, redondeará usando las reglas bancarias (no usando float por cierto). Sin embargo, cuando se muestrea, el redondeo hacia arriba
static_cast<int>(floor(f + .5))
produce menos ruido de muestreo, lo que aumenta el rango dinámico. Al alinear píxeles, es decir, convertir una posición en coordenadas de pantalla, el uso de cualquier otro método de redondeo producirá agujeros, huecos y otros artefactos.fuente
Una razón simple podría ser que existen diferentes métodos para redondear números, por lo que, a menos que conozca el método utilizado, puede obtener resultados diferentes.
Con floor (), puede ser coherente con los resultados. Si el flotador es .5 o mayor, agregarlo aumentará al siguiente int. Pero .49999 simplemente eliminará el decimal.
fuente
round()
hace.floor(x + 0.5)
hace.nearbyint(x)
, que usa un redondeo sensato (al par más cercano), siempre que no se haya metido con el entorno de punto flotante.Muchos programadores adaptan modismos que aprendieron al programar con otros lenguajes. No todos los idiomas tienen una
round()
función, y en esos idiomas es normal usarlosfloor(x + 0.5)
como sustitutos. Cuando estos programadores comienzan a usar C ++, no siempre se dan cuenta de que hay unround()
, continúan usando el estilo al que están acostumbrados.En otras palabras, solo porque vea mucho código que hace algo, no significa que haya una buena razón para hacerlo. Puede encontrar ejemplos de esto en todos los lenguajes de programación. Recuerde la ley de Sturgeon :
fuente