Pourquoi Math.floor renvoie-t-il un double?

104

Javadoc officiel dit que Math.floor()renvoie a doublequi est "égal à un entier mathématique", mais alors pourquoi ne devrait-il pas renvoyer un int?

Raibaz
la source

Réponses:

80

Selon le même Javadoc:

Si l'argument est NaNou un infini ou un zéro positif ou un zéro négatif, le résultat est le même que l'argument. Je ne peux pas faire ça avec un int.

La doublevaleur la plus élevée est également plus grande que la plus grande int, il faudrait donc qu'elle soit a long.

Krosenvold
la source
41
semble incompatible avec les fonctions Math.Round, qui renvoient int / long et gèrent les cas spéciaux d'une manière différente.
zod
1
Notez que le Javadoc dit qu'il renvoie "la plus grande (la plus proche de l'infini positif) * la valeur en virgule flottante * qui est inférieure ou égale à l'argument et est égale à un entier mathématique" . Étant donné une valeur x> 2 ^ 53 qui ne sera pas la même que la valeur avec sa partie fractionnaire tronquée. C'est peut-être un peu plus petit que cela.
Jim Garrison le
16

C'est pour la précision. Le type de données double a une mantisse de 53 bits. Cela signifie entre autres qu'un double peut représenter tout entier jusqu'à 2 ^ 53 sans perte de précision.

Si vous stockez un nombre aussi grand dans un entier, vous obtiendrez un débordement. Les nombres entiers n'ont que 32 bits.

Renvoyer l'entier sous la forme d'un double est la bonne chose à faire ici car il offre une plage de nombres utile beaucoup plus large qu'un entier.

Nils Pipenbrinck
la source
Il pourrait revenir longtemps pour faire face à de telles valeurs, bien sûr. Cependant, vous devrez toujours déterminer quoi faire avec les doubles> 2 ^ 63.
Jon Skeet le
1
@Jon, c'est vrai, mais cela aurait un impact sur les performances (aucune instruction de conversion de long en double dans tout jeu d'instructions dont je connais). Je me demande ce que fait Math.floor avec les doubles> 2 ^ 53 en premier lieu. Certains résultats ne sont pas représentables.
Nils Pipenbrinck le
Mais alors, la forme pseudo-idiomatique (int) Math.floor (foo), qui apparaît également dans le javadoc officiel est dangereuse car le résultat peut ne pas entrer dans un int, ai-je raison? Et puis encore, quelle est une forme sûre pour utiliser Math.floor, puisque le résultat peut ne pas tenir même dans un long?
Raibaz
10

D'autres vous ont dit pourquoi, je vais vous dire comment arrondir correctement si vous voulez le faire. Si vous n'utilisez que des nombres positifs, vous pouvez utiliser cette instruction:

int a=(int) 1.5;

Cependant, le (int) arrondit toujours vers 0. Ainsi, si vous voulez faire un nombre négatif:

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

Dans mon cas, je ne voulais pas faire ça. J'ai utilisé le code suivant pour faire l'arrondi, et il semble bien gérer tous les cas de bord:

private static long floor(double a)
{
    return (int) Math.floor(a);
}
PearsonArtPhoto
la source
7
Pourquoi ne pas l'utiliser (int) Math.floor(a)? C'est probablement plus efficace et plus court.
Solomon Ucko
@Solomon Ucko à la place de (int) Math.floor(a)vous pouvez simplement écrire (int) a, si a est positif.
Leo Leontev
3

Que voudriez-vous qu'il renvoie si vous lui donniez un double plus grand que le plus grand int ou long?

(Certes, s'il est plus grand que le plus grand long, la précision sera de toute façon faible - ce n'est peut-être pas l'entier théorique le plus proche - mais même ainsi ...)

Jon Skeet
la source
0

Tout comme il y a un entier et une division en virgule flottante en Java, il existe des façons entières et en virgule flottante de faire le plancher:

double f = Math.floor(x);

ou

int k = (int) x; 

mais vous devez toujours faire attention à l'utilisation de floor avec une arithmétique de précision finie: votre calcul de x peut donner quelque chose comme 1.99999999 qui sera réduit à 1, et non à 2 par les deux formes. Il existe de nombreux algorithmes qui doivent contourner cette limitation pour éviter de produire des résultats erronés pour certaines valeurs d'entrée.

Pablo
la source
0

Ainsi, cette erreur et d'autres valeurs non entières peuvent correctement se répercuter sur une série de calculs.

Par exemple, si vous insérez Not a Number (NaN) dans Math.floor, il le transmettra.

S'il retournait un entier, il ne pouvait pas transmettre ces statuts ou erreurs, et vous pourriez obtenir de mauvais résultats d'un calcul antérieur qui semblent bons mais sont erronés après un traitement ultérieur.

Adam Davis
la source