Warum gibt Math.floor ein Double zurück?

103

Offizieller Javadoc sagt, dass Math.floor()eine zurückgegeben doublewird, die "gleich einer mathematischen Ganzzahl" ist, aber warum sollte sie dann keine zurückgeben int?

Raibaz
quelle

Antworten:

80

Nach dem gleichen Javadoc:

Wenn das Argument NaNeine Unendlichkeit oder eine positive Null oder eine negative Null ist, ist das Ergebnis dasselbe wie das Argument. Kann das nicht mit einem machen int.

Der größte doubleWert ist auch größer als der größte int, also müsste es ein sein long.

Krosenvold
quelle
40
scheint nicht mit den Math.Round-Funktionen vereinbar zu sein, die int / long zurückgeben und die Sonderfälle auf andere Weise behandeln.
Zod
1
Beachten Sie, dass der Javadoc sagt, dass er "den größten (der positiven Unendlichkeit am nächsten liegenden) * Gleitkommawert * zurückgibt , der kleiner oder gleich dem Argument ist und einer mathematischen Ganzzahl entspricht" . Bei einem Wert x> 2 ^ 53 ist dies nicht der gleiche Wert wie der Wert, dessen Bruchteil abgeschnitten ist. Es kann durchaus etwas kleiner sein.
Jim Garrison
16

Es ist für Präzision. Der doppelte Datentyp hat eine 53-Bit-Mantisse. Dies bedeutet unter anderem, dass ein Double ohne Präzisionsverlust alles Ganze bis zu 2 ^ 53 darstellen kann.

Wenn Sie eine so große Zahl in einer Ganzzahl speichern, erhalten Sie einen Überlauf. Ganzzahlen haben nur 32 Bit.

Die Ganzzahl als Double zurückzugeben ist hier das Richtige, da sie einen viel größeren nützlichen Zahlenbereich bietet als eine Ganzzahl.

Nils Pipenbrinck
quelle
Es könnte natürlich lange dauern, mit solchen Werten fertig zu werden. Sie müssten jedoch noch herausfinden, was Sie mit Doppel> 2 ^ 63 tun sollen.
Jon Skeet
1
@ Jon, stimmt, aber das würde zu einer Auswirkung auf die Leistung führen (keine Konvertierungsanweisung von lang nach doppelt in einem mir bekannten Befehlssatz). Ich frage mich, was Math.floor überhaupt mit Doppel> 2 ^ 53 macht. Einige Ergebnisse sind nicht darstellbar.
Nils Pipenbrinck
Aber dann ist die pseudo-idiomatische Form (int) Math.floor (foo), die auch im offiziellen Javadoc erscheint, unsicher, da das Ergebnis möglicherweise nicht in ein int passt, stimmt das? Und andererseits, was ist eine sichere Form, um Math.floor zu verwenden, da das Ergebnis möglicherweise nicht einmal in eine lange passt?
Raibaz
10

Andere haben dir das Warum gesagt, ich werde dir sagen, wie man richtig rundet, wenn du das willst. Wenn Sie nur positive Zahlen verwenden, können Sie diese Anweisung verwenden:

int a=(int) 1.5;

Das (int) rundet jedoch immer in Richtung 0. Wenn Sie also eine negative Zahl machen möchten:

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

In meinem Fall wollte ich das nicht tun. Ich habe den folgenden Code verwendet, um die Rundung durchzuführen, und er scheint alle Randfälle gut zu behandeln:

private static long floor(double a)
{
    return (int) Math.floor(a);
}
PearsonArtPhoto
quelle
7
Warum nicht verwenden (int) Math.floor(a)? Es ist wahrscheinlich effizienter und kürzer.
Solomon Ucko
@Solomon Ucko anstelle von (int) Math.floor(a)dir kann einfach schreiben (int) a, wenn a positiv ist.
Leo Leontev
3

Was möchten Sie, dass es zurückkehrt, wenn Sie es doppelt so groß wie das größte int oder long geben?

(Zugegeben, wenn es größer als die größte Länge ist, ist die Genauigkeit ohnehin gering - es ist möglicherweise nicht die nächste theoretische Ganzzahl - aber trotzdem ...)

Jon Skeet
quelle
0

So wie es in Java eine Ganzzahl- und eine Gleitkommadivision gibt, gibt es auch Ganzzahl- und Gleitkomma-Methoden, um Floor auszuführen:

double f = Math.floor(x);

oder

int k = (int) x; 

Sie müssen jedoch immer vorsichtig sein, wenn Sie den Boden mit endlicher Präzisionsarithmetik verwenden: Ihre Berechnung von x kann etwa 1,99999999 ergeben, das von beiden Formen auf 1 und nicht auf 2 gesetzt wird. Es gibt viele Algorithmen, die diese Einschränkung umgehen müssen, um zu vermeiden, dass bei einigen Eingabewerten falsche Ergebnisse erzielt werden.

Pablo
quelle
0

Damit Fehler und andere nicht ganzzahlige Werte eine Reihe von Berechnungen korrekt durchlaufen können.

Wenn Sie beispielsweise Not a Number (NaN) in Math.floor eingeben, wird es weitergegeben.

Wenn es eine Ganzzahl zurückgibt, kann es diesen Status oder diese Fehler nicht weitergeben, und Sie können schlechte Ergebnisse aus einer früheren Berechnung erhalten, die gut aussehen, aber nach der weiteren Verarbeitung falsch sind.

Adam Davis
quelle