Perché Math.floor restituisce un doppio?


104

Javadoc ufficiale dice che Math.floor()restituisce un doubleche è "uguale a un numero intero matematico", ma allora perché non dovrebbe restituire un int?

Risposte:


80

Secondo lo stesso Javadoc:

Se l'argomento è NaNo un infinito o zero positivo o zero negativo, il risultato è lo stesso dell'argomento. Non puoi farlo con un file int.

Il doublevalore più grande è anche maggiore del più grande int, quindi dovrebbe essere a long.


40
sembra incoerente con le funzioni Math.Round, che restituiscono int / long e gestiscono i casi speciali in un modo diverso.
Zod

1
Si noti che Javadoc dice che restituisce "il valore in virgola mobile più grande (più vicino all'infinito positivo) * inferiore o uguale all'argomento ed è uguale a un numero intero matematico" . Dato un valore x> 2 ^ 53 che non sarà lo stesso del valore con la sua parte frazionaria troncata. Potrebbe anche essere un po 'più piccolo di quello.
Jim Garrison,

16

È per la precisione. Il doppio tipo di dati ha una mantissa a 53 bit. Tra l'altro ciò significa che un doppio può rappresentare tutto intero fino a 2 ^ 53 senza perdita di precisione.

Se memorizzi un numero così elevato in un numero intero, otterrai un overflow. I numeri interi hanno solo 32 bit.

Restituire il numero intero come double è la cosa giusta da fare qui perché offre un intervallo di numeri utili molto più ampio di quello che potrebbe fare un intero.


Naturalmente potrebbe tornare molto tempo per far fronte a tali valori. Dovresti comunque capire cosa fare con i doppi> 2 ^ 63.
Jon Skeet

1
@ Jon, vero, ma ciò comporterebbe un impatto sulle prestazioni (nessuna istruzione di conversione da lunga a doppia in qualsiasi set di istruzioni di cui sono a conoscenza). Mi chiedo cosa faccia Math.floor con i doppi> 2 ^ 53 in primo luogo. Alcuni risultati non sono rappresentabili.
Nils Pipenbrinck

Ma poi, la forma pseudo-idiomatica (int) Math.floor (foo), che appare anche nel javadoc ufficiale non è sicura poiché il risultato potrebbe non rientrare in un int, giusto? E poi di nuovo, qual è una forma sicura per utilizzare Math.floor, dal momento che il risultato potrebbe non adattarsi nemmeno a un lungo?
Raibaz

10

Altri ti hanno detto il perché, ti dirò come arrotondare correttamente dato che vuoi farlo. Se intendi utilizzare solo numeri positivi, puoi utilizzare questa affermazione:

int a=(int) 1.5;

Tuttavia, (int) arrotonda sempre verso 0. Quindi, se vuoi fare un numero negativo:

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

Nel mio caso, non volevo farlo. Ho usato il seguente codice per eseguire l'arrotondamento e sembra che gestisca bene tutti i casi limite:

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

7
Perché non usare (int) Math.floor(a)? Probabilmente è più efficiente ed è più breve.
Solomon Ucko

@Solomon Ucko invece di (int) Math.floor(a)te puoi semplicemente scrivere (int) a, se è positivo.
Leo Leontev

3

Cosa vorresti che restituisse se gli dai un doppio più grande del più grande int o long?

(Certo, se è più grande del più lungo lungo, la precisione sarà comunque bassa - potrebbe non essere il numero intero teorico più vicino - ma anche così ...)


0

Proprio come esiste un numero intero e una divisione in virgola mobile in Java, ci sono modi interi e in virgola mobile per eseguire floor:

double f = Math.floor(x);

o

int k = (int) x; 

ma devi sempre stare attento quando usi floor con aritmetica di precisione finita: il tuo calcolo di x può produrre qualcosa come 1.99999999 che sarà floor a 1, non a 2 da entrambe le forme. Ci sono molti algoritmi là fuori che devono aggirare questa limitazione per evitare di produrre risultati errati per alcuni valori di input.


0

In modo che l'errore e altri valori non interi possano ricadere correttamente in una serie di calcoli.

Ad esempio, se inserisci Not a Number (NaN) in Math.floor, lo trasmetterà.

Se restituisse un numero intero, non potrebbe trasmettere questi stati o errori e potresti ottenere risultati negativi da un calcolo precedente che sembra buono ma è sbagliato dopo un'ulteriore elaborazione.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.