¿Por qué Math.floor devuelve un doble?

104

El Javadoc oficial dice que Math.floor()devuelve un double"igual a un entero matemático", pero entonces ¿por qué no debería devolver un int?

Raibaz
fuente

Respuestas:

80

Según el mismo Javadoc:

Si el argumento es NaNinfinito, cero positivo o cero negativo, el resultado es el mismo que el argumento. No puedo hacer eso con un int.

El doublevalor más grande también es más grande que el más grande int, por lo que debería ser a long.

krosenvold
fuente
40
parece inconsistente con las funciones Math.Round, que devuelven int / long y manejan los casos especiales de una manera diferente.
zod
1
Observe que el Javadoc dice que devuelve "el mayor (más cercano al infinito positivo) * valor de punto flotante * que sea menor o igual al argumento y es igual a un entero matemático" . Dado un valor x> 2 ^ 53 que no será el mismo que el valor con su parte fraccionaria truncada. Bien puede ser un poco más pequeño que eso.
Jim Garrison
16

Es por precisión. El tipo de datos doble tiene una mantisa de 53 bits. Entre otras cosas, eso significa que un doble puede representar todo entero hasta 2 ^ 53 sin pérdida de precisión.

Si almacena un número tan grande en un entero, obtendrá un desbordamiento. Los enteros solo tienen 32 bits.

Devolver el entero como un doble es lo correcto aquí porque ofrece un rango de números útiles mucho más amplio que el que podría tener un entero.

Nils Pipenbrinck
fuente
Podría volver mucho tiempo para hacer frente a tales valores, por supuesto. Sin embargo, aún tendrías que averiguar qué hacer con los dobles> 2 ^ 63.
Jon Skeet
1
@Jon, cierto, pero eso daría como resultado un impacto en el rendimiento (no hay instrucción de conversión de larga a doble en ningún conjunto de instrucciones que yo sepa). Me pregunto qué hace Math.floor con dobles> 2 ^ 53 en primer lugar. Algunos resultados no son representables.
Nils Pipenbrinck
Pero entonces, la forma pseudo-idiomática (int) Math.floor (foo), que también aparece en el javadoc oficial no es segura ya que el resultado puede no encajar en un int, ¿verdad? Y, de nuevo, ¿cuál es una forma segura de usar Math.floor, ya que el resultado puede no encajar ni siquiera en un largo?
Raibaz
10

Otros te han dicho el por qué, yo te diré cómo redondear correctamente dado que quieres hacer esto. Si solo va a usar números positivos, puede usar esta declaración:

int a=(int) 1.5;

Sin embargo, el (int) siempre se redondea hacia 0. Por lo tanto, si desea hacer un número negativo:

int a=(int) -1.5; //Equal to -1

En mi caso, no quería hacer esto. Usé el siguiente código para hacer el redondeo, y parece manejar bien todos los casos extremos:

private static long floor(double a)
{
    return (int) Math.floor(a);
}
PearsonArteFoto
fuente
7
¿Por qué no usar (int) Math.floor(a)? Probablemente sea más eficiente y más corto.
Solomon Ucko
@Solomon Ucko en lugar de (int) Math.floor(a)simplemente puede escribir (int) a, si a es positivo.
Leo Leontev
3

¿Qué le gustaría que regresara si le diera un doble más grande que el mayor int o long?

(Es cierto que si es más grande que el largo más grande, la precisión será baja de todos modos; puede que no sea el entero teórico más cercano, pero aun así ...)

Jon Skeet
fuente
0

Así como hay una división de entero y una de punto flotante en Java, hay formas de entero y de punto flotante para hacer el piso:

double f = Math.floor(x);

o

int k = (int) x; 

pero siempre debe tener cuidado con el uso de piso con aritmética de precisión finita: su cálculo de x puede producir algo como 1.99999999, que será reducido a 1, no a 2 por ambas formas. Existen muchos algoritmos que necesitan solucionar esta limitación para evitar producir resultados incorrectos para algunos valores de entrada.

Pablo
fuente
0

De modo que el error y otros valores que no sean enteros puedan pasar correctamente en cascada a través de una serie de cálculos.

Por ejemplo, si introduce Not a Number (NaN) en Math.floor, lo pasará.

Si devolvió un número entero, no podría pasar estos estados o errores, y podría obtener malos resultados de un cálculo anterior que se ve bien pero es incorrecto después de un procesamiento posterior.

Adam Davis
fuente