c# - round - math.floor java
¿Por qué no vuelve Math.Round/Floor/Ceiling long o int? (4)
Dejando de lado los argumentos del rango, ninguna de estas respuestas aborda lo que, para mí, es un problema fundamental para devolver un número de punto flotante cuando realmente desea un entero exacto. Me parece que el número de punto flotante calculado podría ser menor o mayor que el entero deseado por un pequeño error de redondeo, por lo que la operación de conversión podría crear un error de apagado. Creo que, en lugar de lanzar, debe aplicar una función de redondeo entero (no doble) al resultado doble de floor()
. O bien escribe tu propio código. Las versiones de biblioteca C de floor()
y ceil()
son muy lentas de todos modos.
¿Es esto cierto, o me estoy perdiendo algo? Hay algo acerca de una representación exacta de enteros en un estándar de punto flotante IEEE, pero no estoy seguro de si esto hace que la conversión sea segura.
Preferiría tener un control de rango en la función (si es necesario para evitar el desbordamiento) y regresar mucho. Para mi propio código privado, puedo omitir la verificación de rango. He estado haciendo esto:
long int_floor(double x)
{
double remainder;
long truncate;
truncate = (long) x; // rounds down if + x, up if negative x
remainder = x - truncate; // normally + for + x, - for - x
//....Adjust down (toward -infinity) for negative x, negative remainder
if (remainder < 0 && x < 0)
return truncate - 1;
else
return truncate;
}
Las contrapartes existen para ceil()
y round()
con diferentes consideraciones para los números negativos y positivos.
Cada vez que uso Math.Round/Floor/Ceiling
, siempre Math.Round/Floor/Ceiling
a int
(o tal vez long
si es necesario). ¿Por qué exactamente devuelven el double
si siempre está devolviendo un entero?
El resultado podría no encajar en un int (o un largo). El rango de un doble es mucho mayor.
Rango aproximado de doble: ± 5.0 × 10 −324 a ± 1.7 × 10 308
Estoy de acuerdo con la respuesta de Mark de que el resultado podría no encajar en long
, pero podría preguntarse: ¿qué pasaría si C # tuviera un tipo mucho más long
? Bueno, esto es lo que sucede en Python con sus enteros de longitud arbitraria:
>>> round(1.23e45)
1229999999999999973814869011019624571608236032
La mayoría de los dígitos son "ruido" del error de redondeo de punto flotante. Quizás parte de la motivación para que Round
/ Floor
/ Ceiling
retornara el double
en C # era evitar la ilusión de falsa precisión.
Una explicación alternativa es que el módulo Math
.NET utiliza código escrito en C, en el cual el floor y el ceil devuelven los tipos de punto flotante.
No hay ninguna razón dada en los documentos que pude encontrar. Mi mejor conjetura es que si está trabajando con dobles, es probable que desee que cualquier operación en dobles devuelva un doble. Redondearlo para lanzarlo a un int fue considerado por el diseñador de lenguaje menos común que redondear y mantener como un doble.
Puede escribir su propio método que lo convierte en un int para usted en aproximadamente 2 líneas de código, y mucho menos trabajo que publicar una pregunta en el desbordamiento de pila ...