Por que Math.floor retorna um double?


104

Javadoc oficial diz que Math.floor()retorna um doubleque é "igual a um inteiro matemático", mas então por que não deveria retornar um int?

Respostas:


80

De acordo com o mesmo Javadoc:

Se o argumento for NaNou infinito ou zero positivo ou zero negativo, o resultado será o mesmo que o argumento. Não posso fazer isso com um int.

O maior doublevalor também é maior do que o maior int, então teria que ser a long.


40
parece inconsistente com as funções Math.Round, que retornam int / long e tratam os casos especiais de uma maneira diferente.
zod

1
Observe que o Javadoc diz que ele retorna "o maior (mais próximo do infinito positivo) * valor de ponto flutuante * menor ou igual ao argumento e igual a um inteiro matemático" . Dado um valor x> 2 ^ 53 que não será o mesmo que o valor com sua parte fracionária truncada. Pode muito bem ser um pouco menor do que isso.
Jim Garrison,

16

É para precisão. O tipo de dados duplo tem uma mantissa de 53 bits. Entre outras coisas, isso significa que um duplo pode representar todo o todo até 2 ^ 53 sem perda de precisão.

Se você armazenar um número tão grande em um inteiro, terá um estouro. Os inteiros têm apenas 32 bits.

Retornar o inteiro como um duplo é a coisa certa a se fazer aqui, porque oferece um intervalo de números útil muito mais amplo do que um inteiro.


É claro que poderia demorar muito para lidar com tais valores. Você ainda teria que descobrir o que fazer com duplos> 2 ^ 63.
Jon Skeet

1
@Jon, é verdade, mas isso resultaria em um impacto no desempenho (nenhuma instrução de conversão de long para double em qualquer conjunto de instruções que eu conheça). Eu me pergunto o que Math.floor faz com dobros> 2 ^ 53 em primeiro lugar. Alguns resultados não são representáveis.
Nils Pipenbrinck

Mas então, a forma pseudo-idiomática (int) Math.floor (foo), que também aparece no javadoc oficial, não é segura, pois o resultado pode não caber em um int, certo? E então, qual é uma forma segura de usar Math.floor, já que o resultado pode não caber nem em um arquivo longo?
Raibaz

10

Outros disseram a você o porquê, vou lhe dizer como arredondar corretamente, já que você deseja fazer isso. Se você pretende usar apenas números positivos, pode usar esta instrução:

int a=(int) 1.5;

No entanto, o (int) sempre é arredondado para 0. Portanto, se você quiser fazer um número negativo:

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

No meu caso, eu não queria fazer isso. Usei o seguinte código para fazer o arredondamento e parece que ele trata bem todos os casos extremos:

private static long floor(double a)
{
    return (int) Math.floor(a);
}

7
Por que não usar (int) Math.floor(a)? Provavelmente é mais eficiente e mais curto.
Solomon Ucko

@Solomon Ucko em vez de (int) Math.floor(a)simplesmente escrever (int) a, se a for positivo.
Leo Leontev

3

O que você gostaria que ele retornasse se desse a ele um dobro maior do que o maior int ou longo?

(Admitidamente, se for maior do que o maior longo, a precisão será baixa de qualquer maneira - pode não ser o número inteiro teórico mais próximo - mas mesmo assim ...)


0

Assim como há um inteiro e uma divisão de ponto flutuante em Java, existem maneiras de inteiros e de ponto flutuante de fazer floor:

double f = Math.floor(x);

ou

int k = (int) x; 

mas você sempre precisa ter cuidado ao usar floor com aritmética de precisão finita: seu cálculo de x pode render algo como 1.99999999 que será reduzido a 1, não 2 por ambas as formas. Existem muitos algoritmos por aí que precisam contornar essa limitação para evitar a produção de resultados errados para alguns valores de entrada.


0

Assim, esse erro e outros valores não inteiros podem ser corretamente cascateados por uma série de cálculos.

Por exemplo, se você alimentar Not a Number (NaN) em Math.floor, ele o passará adiante.

Se ele retornasse um número inteiro, não poderia passar esses status ou erros adiante, e você poderia obter resultados ruins de um cálculo anterior que parecem bons, mas estão errados após o processamento posterior.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.