Dlaczego Math.floor zwraca double?

104

Oficjalny Javadoc mówi, że Math.floor()zwraca a, doublektóre jest „równe matematycznej liczbie całkowitej”, ale dlaczego nie miałoby zwrócić int?

Raibaz
źródło

Odpowiedzi:

80

Według tego samego Javadoc:

Jeśli argumentem jest NaNnieskończoność lub dodatnie zero lub ujemne zero, to wynik jest taki sam jak argument. Nie można tego zrobić z plikiem int.

Największa doublewartość jest również większa niż największa int, więc musiałby to być long.

krosenvold
źródło
41
wydaje się niespójne z funkcjami Math.Round, które zwracają int / long i obsługują przypadki specjalne w inny sposób.
zod
1
Zauważ, że Javadoc mówi, że zwraca „największą (najbliższą dodatniej nieskończoności) * wartość zmiennoprzecinkową * mniejszą lub równą argumentowi i równą matematycznej liczbie całkowitej” . Biorąc pod uwagę wartość x> 2 ^ 53 , która nie będzie taka sama, jak wartość z obciętą częścią ułamkową. Może być trochę mniejszy.
Jim Garrison,
16

To dla precyzji. Podwójny typ danych ma 53-bitową mantysę. Między innymi oznacza to, że podwójna może reprezentować całość do 2 ^ 53 bez utraty precyzji.

Jeśli zapiszesz tak dużą liczbę w liczbie całkowitej, otrzymasz przepełnienie. Liczby całkowite mają tylko 32 bity.

Zwracanie liczby całkowitej jako liczby podwójnej jest tutaj właściwą rzeczą, ponieważ oferuje znacznie szerszy użyteczny zakres liczbowy niż liczba całkowita.

Nils Pipenbrinck
źródło
Oczywiście zajęcie się takimi wartościami może zwrócić dużo czasu. Nadal jednak musiałbyś wymyślić, co zrobić z podwójnymi> 2 ^ 63.
Jon Skeet
1
@Jon, prawda, ale miałoby to wpływ na wydajność (brak instrukcji konwersji z długich na podwójne w żadnym zestawie instrukcji, o którym wiem). Zastanawiam się, co robi Math.floor z liczbami podwójnymi> 2 ^ 53 na pierwszym miejscu. Niektórych wyników nie da się przedstawić.
Nils Pipenbrinck
Ale z drugiej strony pseudo-idiomatyczna postać (int) Math.floor (foo), która pojawia się również w oficjalnym javadoc, jest niebezpieczna, ponieważ wynik może nie pasować do int, mam rację? A z drugiej strony, jaka jest bezpieczna forma korzystania z Math.floor, skoro wynik może nie pasować nawet do długiego?
Raibaz
10

Inni powiedzieli ci, dlaczego, powiem ci, jak poprawnie zaokrąglić, skoro chcesz to zrobić. Jeśli zamierzasz używać tylko liczb dodatnich, możesz użyć tego stwierdzenia:

int a=(int) 1.5;

Jednak (int) zawsze zaokrągla się w kierunku 0. Tak więc, jeśli chcesz obliczyć liczbę ujemną:

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

W moim przypadku nie chciałem tego robić. Użyłem następującego kodu, aby wykonać zaokrąglenie i wydaje się, że dobrze radzi sobie ze wszystkimi przypadkami brzegowymi:

private static long floor(double a)
{
    return (int) Math.floor(a);
}
PearsonArtPhoto
źródło
7
Dlaczego nie używać (int) Math.floor(a)? Prawdopodobnie jest wydajniejszy i krótszy.
Solomon Ucko
@Solomon Ucko zamiast (int) Math.floor(a)ciebie możesz po prostu napisać (int) a, jeśli jest pozytywne.
Leo Leontev
3

Co byś chciał, żeby zwrócił, jeśli dasz mu dwukrotnie więcej niż największy int lub long?

(Co prawda, jeśli jest większy od największego długości, precyzja i tak będzie niska - może to nie być najbliższa teoretyczna liczba całkowita - ale mimo to ...)

Jon Skeet
źródło
0

Podobnie jak w Javie istnieje liczba całkowita i dzielenie zmiennoprzecinkowe, istnieją sposoby na liczby całkowite i zmiennoprzecinkowe:

double f = Math.floor(x);

lub

int k = (int) x; 

ale zawsze musisz być ostrożny przy używaniu floor z arytmetyką o skończonej precyzji: twoje obliczenie x może dać coś w rodzaju 1.99999999, który zostanie zmieniony na 1, a nie 2 przez obie formy. Istnieje wiele algorytmów, które muszą obejść to ograniczenie, aby uniknąć generowania błędnych wyników dla niektórych wartości wejściowych.

Pablo
źródło
0

Tak więc błąd i inne wartości inne niż całkowite mogą poprawnie przechodzić kaskadowo przez serię obliczeń.

Na przykład, jeśli wprowadzisz Not a Number (NaN) do Math.floor, przekaże go dalej.

Jeśli zwrócił liczbę całkowitą, nie mógł przekazać tego stanu lub błędów, a wcześniejsze obliczenia mogą powodować złe wyniki, które wyglądają dobrze, ale są błędne po dalszym przetwarzaniu.

Adam Davis
źródło