Warum gibt Math.Floor (Double) einen Wert vom Typ Double zurück?


103

Ich muss den ganzzahligen Wert auf der linken Seite von einer Dezimalstelle oder einem Doppelwert erhalten. Zum Beispiel: Ich muss den Wert 4 von 4.6 erhalten. Ich habe versucht, die Math.Floor-Funktion zu verwenden, aber sie gibt einen doppelten Wert zurück, zum Beispiel: Sie gibt 4.0 von 4.6 zurück. In der MSDN-Dokumentation wird angegeben, dass ein ganzzahliger Wert zurückgegeben wird. Vermisse ich hier etwas? Oder gibt es einen anderen Weg, um das zu erreichen, wonach ich suche?


2
In der MSDN-Dokumentation wird angegeben, dass ein ganzzahliger Wert zurückgegeben wird . In der MSDN-Dokumentation heißt es, dass Math.Floor System.Double und nicht Integer zurückgibt.
Breitband

Ein ganzzahliger Wert wird effektiv benötigt, bedeutet jedoch nicht, dass er in einem "int" oder "long" gespeichert werden kann. Ein "double" speichert erfolgreich alle Integer-Werte in einem viel größeren Bereich als nur "int". Beachten Sie, dass einige Integer-Werte gerundet werden können, wenn der Mantissenteil nicht genügend Bits hat, um alle Ziffern des Integer-Werts zu speichern, wenn sein Basis-2-Exponent geht über 52 hinaus: Diese Rundung von Ganzzahlwerten in "double" kann für Ganzzahlen über 2 ^ 52 oder unter -2 ^ 52 auftreten, aber das Ergebnis ist immer noch die nächste darstellbare Ganzzahl; Wenn Sie "(long) Floor (x)" verwenden, kann die Konvertierung weitgehend falsch sein.
verdy_p

Beachten Sie jedoch, dass der gültige Bereich von ganzzahligen Werten, die in einem "Doppel" dargestellt werden können, extrem groß ist, mit absoluten Werten bis zu: (1 + (1 - 2 ^ −52)) × 2 ^ 1023 ≈ 1.7976931348623157E308; es ist viel mehr als 2 ^ 63-1 mit "lang". Der Bereich von Ganzzahlen, die alle eindeutig gespeichert werden können, ist jedoch eingeschränkter, da ein "Double" nur 52 Bits für die Mantisse enthält (plus 1 Bit für das höchstwertige Bit, das nicht gespeichert ist), was bedeutet, dass "Double" nur speichern kann ganze Zahlen genau dann, wenn ihr absoluter Wert unter 2 ^ 53 liegt.
verdy_p

Leider gibt Math.Floor () keinen Variablentyp "Number" intern mit "Long" zurück, wenn möglich, oder "Double", ansonsten nur für große gerundete Ganzzahlen. Und die Standard-Mathematikbibliothek verarbeitet einen solchen einheitlichen Variablennummertyp nicht. Es gibt andere Mathematikbibliotheken, die einen einheitlichen Zahlentyp implementieren, einschließlich langer, doppelter oder großer Ganzzahlen, die in gepackten Dezimal- oder Binärzahlen ohne Verlust des unterstützten Bereichs oder der Genauigkeit codiert sind.
verdy_p

Antworten:


146

Der Bereich von doubleist viel breiter als der Bereich von intoder long. Betrachten Sie diesen Code:

double d = 100000000000000000000d;
long x = Math.Floor(d); // Invalid in reality

Die Ganzzahl liegt außerhalb des Bereichs von long- was würden Sie also erwarten?

Normalerweise wissen Sie, dass der Wert tatsächlich im Bereich von intoder liegt long, also setzen Sie ihn um:

double d = 1000.1234d;
int x = (int) Math.Floor(d);

Aber die Verantwortung für diese Besetzung liegt beim Entwickler, nicht bei sich Math.Floorselbst. Es wäre unnötig einschränkend gewesen, es mit einer Ausnahme für alle Werte außerhalb des Bereichs von nur zum Scheitern zu bringen long.


2
Floor gibt eine ganzzahlige Darstellung von double zurück, und für wissenschaftliche Berechnungen wird double zurückgegeben. Diese Antwort ist nicht korrekt, da double 64 Bit und long ebenfalls 64 Bit hat, double jedoch keine exakten Ziffern von niederwertigen Bits speichern kann, selbst wenn es korrekt gespeichert werden kann in lang.
Akash Kava

1
@ Jon: Wieso hast du die Debatte darüber, wie man eine positive Zahl in C # negativ macht, nicht abgewogen?: Stackoverflow.com/questions/1348080/…
MusiGenesis

3
@ Jon: Nimm dir Zeit. Es stellt sich heraus, dass die Community herausgefunden hat, dass das Multiplizieren einer positiven Zahl mit -1 sie negativ macht. Bei StackOverflow ist alles in Ordnung.
MusiGenesis

1
@javapowered: Nein, (int) 15.0 ist nicht 0. Etwas anderes ist schiefgegangen, aber wir können nicht sagen, was daraus wird. Bitte erstellen Sie ein kurzes, aber vollständiges Programm, das dies demonstriert, und stellen Sie dann eine Frage. Ich vermute, Sie werden es schwer finden, zu reproduzieren ...
Jon Skeet

1
@MusiGenesis: <code> (int) IGNORE_RATIO * Volume </ code> wird als <code> (int) 0,15 * Volume </ code> berechnet, die Typumwandlung gilt jedoch nur für das Verhältnis, nicht für das Ergebnis des Produkts, und Sie erhalten <code> 0 * Volume </ code> dh Null! Verwenden Sie stattdessen <code> (int) (IGNORE_RATIO * Volume) </ code>, um IHREN Fehler zu beheben.
verdy_p

11

Laut MSDN gibt Math.Floor (double) ein Double zurück: http://msdn.microsoft.com/en-us/library/e0b5f0xb.aspx

Wenn Sie es als int wollen:

int result = (int)Math.Floor(yourVariable);

Ich kann sehen, wie irreführend der MSDN-Artikel sein kann. Sie hätten angeben müssen, dass das Ergebnis zwar eine "Ganzzahl" ist (in diesem Fall eine ganze Zahl), aber immer noch vom Typ TYPE Double ist


Danke für Ihre Antwort. Eigentlich habe ich mir diesen Artikel angesehen: msdn.microsoft.com/en-us/library/e0b5f0xb.aspx Aber trotzdem werde ich Ihren Vorschlag versuchen. Danke dir.

Gut wahr, es heißt oben "gibt eine ganze Zahl zurück", aber der Typ ist darunter angegeben: public static double Floor (double d)
Neil N

3
Ganzzahl! = int( answers.com/integer ) - Ganzzahlen können in gespeichert werden Double(siehe Jons Antwort), und es gibt unendlich viele Ganzzahlen, die nicht in einer gespeichert werden können int.
Shog9

Shog, ich habe nicht gesagt, dass sie es nicht können. Was ich sagte war "es ist immer noch von TYPE Double"
Neil N

1
@Neil: richtig - wollte nur den Unterschied zwischen "Ganzzahl" (Name einer Menge) und int(Name eines Typs) hervorheben .
Shog9

4

Wenn Sie nur den ganzzahligen Teil einer Zahl benötigen, wandeln Sie die Zahl in eine um int. Dadurch wird die Zahl am Dezimalpunkt abgeschnitten.

double myDouble = 4.6;
int myInteger = (int)myDouble;

2
Es ist wichtig zu beachten, dass sich das Casting für negative Zahlen intanders verhält als Floor. Floorwird immer auf die negativste Zahl abgeschnitten, während das Casting auf int0 gekürzt wird.
Magnus


0

Floor belässt es als Doppel, sodass Sie mehr Doppelberechnungen damit durchführen können. Wenn Sie es als int möchten, wandeln Sie das Ergebnis von floor als int um. Wirf das ursprüngliche Double nicht als Int, da die Regeln für Floor für negative Zahlen unterschiedlich sind (IIRC).


0
Convert.ToInt32(Math.Floor(Convert.ToDouble(value)))

Dies gibt Ihnen den genauen Wert, den Sie möchten, wenn Sie 4.6ihn 4als Ausgabe zurückgeben.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.