Dlaczego Math.Floor (Double) zwraca wartość typu Double?


103

Muszę uzyskać wartość całkowitą po lewej stronie z ułamka dziesiętnego lub podwójnego. Na przykład: muszę uzyskać wartość 4 z 4,6. Próbowałem użyć funkcji Math.Floor, ale zwraca podwójną wartość, na przykład: zwraca 4,0 z 4,6. Dokumentacja MSDN mówi, że zwraca wartość całkowitą. Czy coś mi umyka? A może jest inny sposób na osiągnięcie tego, czego szukam?


2
Dokumentacja MSDN mówi, że zwraca wartość całkowitą . Dokumentacja MSDN stwierdza, że ​​Math.Floor zwraca System.Double, a nie liczbę całkowitą.
szerokopasmowy

Wartość całkowita jest efektywnie potrzebna, ale nie oznacza to, że może być przechowywana w „int” lub „long”. „Double” z powodzeniem przechowuje wszystkie wartości całkowite w znacznie szerszym zakresie niż tylko „int” Zauważ, że niektóre wartości całkowite mogą być zaokrąglane, gdy część mantysy nie ma wystarczającej liczby bitów do przechowywania wszystkich cyfr wartości całkowitej, gdy jej wykładnik o podstawie 2 przekracza 52: to zaokrąglanie wartości całkowitych w „double” może wystąpić w przypadku liczb całkowitych powyżej 2 ^ 52 lub poniżej -2 ^ 52, ale wynikiem nadal będzie najbliższa reprezentowalna liczba całkowita; jeśli użyjesz „(long) Floor (x)”, konwersja może być w dużej mierze błędna.
verdy_p

Należy jednak zauważyć, że prawidłowy zakres wartości całkowitych, które mogą być reprezentowane w postaci „podwójnej”, jest niezwykle duży, z wartościami bezwzględnymi do: (1 + (1 - 2 ^ −52)) × 2 ^ 1023 ≈ 1,7976931348623157E308; to znacznie więcej niż 2 ^ 63-1 z „długim”. Jednak zakres liczb całkowitych, które można przechowywać oddzielnie, jest bardziej ograniczony, ponieważ „double” ma tylko 52 bity dla mantysy (plus 1 bit dla najbardziej znaczącego bitu, który nie jest przechowywany), co oznacza, że ​​„double” może przechowywać tylko liczby całkowite tylko wtedy, gdy ich wartość bezwzględna jest mniejsza niż 2 ^ 53.
verdy_p

Niestety, Math.Floor () nie zwraca wewnętrznie zmiennej typu „Number”, używając „Long”, jeśli to możliwe, lub „Double” w przeciwnym razie tylko dla dużych zaokrąglonych liczb całkowitych. A standardowa biblioteka Math nie obsługuje takiego zunifikowanego typu liczby zmiennych. Istnieją inne biblioteki matematyczne implementujące ujednolicony typ liczb, w tym długie, podwójne lub duże liczby całkowite zakodowane w upakowanych dziesiętnych lub binarnych bez utraty obsługiwanego zakresu lub precyzji.
verdy_p

Odpowiedzi:


146

Zakres doublejest znacznie szerszy niż zakres intlub long. Rozważ ten kod:

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

Liczba całkowita jest poza zakresem long- więc czego można się spodziewać?

Zwykle wiesz, że wartość będzie w rzeczywistości mieściła się w zakresie intlub long, więc rzucasz:

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

ale odpowiedzialność za tę obsadę spoczywa na deweloperze, a nie na Math.Floorsobie. Byłoby niepotrzebnie restrykcyjne, gdyby po prostu zawodziło, z wyjątkiem wszystkich wartości spoza zakresu long.


2
Floor zwraca całkowitą reprezentację double i zwraca double dla obliczeń naukowych, ta odpowiedź nie jest poprawna, ponieważ double ma 64 bity i long ma również 64 bity, ale double nie może przechowywać dokładnych cyfr mniej znaczących bitów, nawet jeśli można je poprawnie zapisać w długim.
Akash Kava

1
@Jon: dlaczego nie ważyłeś się w debacie szalejącej nad tym, jak uczynić liczbę dodatnią ujemną w C # ?: stackoverflow.com/questions/1348080/ ...
MusiGenesis

3
@Jon: nie spiesz się. Okazuje się, że społeczność odkryła, że ​​pomnożenie liczby dodatniej przez -1 spowoduje, że będzie ona ujemna. Wszystko jest w porządku w StackOverflow.
MusiGenesis

1
@javapowered: Nie, (int) 15.0 to nie 0. Coś jeszcze poszło nie tak, ale nie możemy powiedzieć, co z tego. Utwórz krótki, ale kompletny program demonstrujący to, a następnie zadaj pytanie. Podejrzewam, że będzie ci trudno odtworzyć ...
Jon Skeet

1
@MusiGenesis: <code> (int) IGNORE_RATIO * Volume </code> jest obliczany jako <code> (int) 0.15 * Volume </code>, ale typoszereg dotyczy tylko współczynnika, a nie wyniku produktu i otrzymujesz <code> 0 * Volume </code> czyli zero! Zamiast tego użyj <code> (int) (IGNORE_RATIO * Volume) </code>, aby rozwiązać TWÓJ błąd.
verdy_p

11

Według MSDN, Math.Floor (double) zwraca double: http://msdn.microsoft.com/en-us/library/e0b5f0xb.aspx

Jeśli chcesz to jako int:

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

Widzę, że artykuł MSDN może wprowadzać w błąd, powinni byli określić, że chociaż wynik jest liczbą całkowitą (w tym przypadku oznacza liczbę całkowitą), nadal jest typu TYP Podwójna


Dziękuję za odpowiedź. Właściwie patrzyłem na ten artykuł: msdn.microsoft.com/en-us/library/e0b5f0xb.aspx Ale mimo wszystko spróbuję twojej sugestii. Dziękuję Ci.

Cóż, prawda, na górze jest napisane „zwraca liczbę całkowitą”, ale typ jest określony poniżej: public statyczny double Floor (double d)
Neil N

3
integer! = int( respons.com/integer ) - liczby całkowite mogą być przechowywane w Double(zobacz odpowiedź Jona), a istnieje nieskończona liczba liczb całkowitych, których nie można przechowywać w pliku int.
Shog9

Shog, nie powiedziałem, że nie mogą. To, co powiedziałem, brzmiało: "nadal jest typu podwójnego TYPE"
Neil N

1
@Neil: right - chciałem tylko podkreślić różnicę między „integer” (nazwa zestawu) a int(nazwa typu).
Shog9

4

Jeśli potrzebujesz tylko części całkowitej liczby, rzuć liczbę na int. Spowoduje to obcięcie liczby w miejscu dziesiętnym.

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

2
Należy pamiętać, że rzutowanie intzachowuje się inaczej niż Floordla liczb ujemnych. Floorbędzie zawsze skracany do najbardziej ujemnej liczby, podczas gdy rzucanie do intbędzie skracane w kierunku 0.
Magnus


0

Podłoga pozostawia ją jako podwójną, dzięki czemu możesz wykonać więcej podwójnych obliczeń. Jeśli chcesz, aby było to int, rzuć wynik floor jako int. Nie rzutuj oryginalnej liczby podwójnej jako int, ponieważ reguły podłogi są różne (IIRC) dla liczb ujemnych.


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

To da ci dokładną wartość, jaką chcesz, jeśli przyjmiesz, 4.6że zwraca 4jako wynik.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.