2011-09-02 21 views
64

Gdy zadzwonię pod numer Math.ceil(5.2), zwracana jest wartość double6.0. Moją naturalną skłonnością było sądzić, że Math.ceil(double a) zwróci long. Z dokumentacji:Dlaczego Math.ceil zwraca double?

ceil(double a)

zwraca najmniejszą (najbliżej ujemnej nieskończoności) double wartość , która jest nie mniejsza niż argument i jest równa matematycznego całkowitej.

Dlaczego zamiast tego zwracamy wartość double zamiast long, gdy wynikiem jest liczba całkowita? Myślę, że zrozumienie przyczyny tego problemu może pomóc mi lepiej zrozumieć Javę. Pomoże mi też dowiedzieć się, czy wpadnę w kłopoty, rzucając na long, np. jest

long b = (long)Math.ceil(a);

zawsze to, co myślę, że powinno być? Obawiam się, że mogą istnieć pewne problemy graniczne, które są problematyczne.

+0

Zobacz http://stackoverflow.com/questions/3412449/why-does-math-round-return-a-long-but-math-floor-return-double – starblue

Odpowiedz

61

Zakres double jest większy niż long. Na przykład:

double x = Long.MAX_VALUE; 
x = x * 1000; 
x = Math.ceil(x); 

Czego można oczekiwać ostatni wiersz zrobić, jeśli Math.ceil powrócił long?

Należy zauważyć, że przy bardzo dużych wartościach (dodatnich lub ujemnych) liczby kończą się bardzo rzadko - więc następna liczba całkowita większa od liczby całkowitej x nie będzie x + 1, jeśli widzisz co mam na myśli.

+0

Myślę, że w swoim ostatnim zdaniu jesteś mówiąc o luźnej precyzji, ale myślę, że to nie zależy od wysokiej liczby, ale od liczby cyfr znaczących (w binarnym). Spróbuję znaleźć przykład. – aalku

+0

@ user270349: Bezwzględna luka między kolejnymi podwójnymi wartościami staje się większa, gdy wartość staje się większa. Liczba reprezentowanych cyfr znaczących pozostaje taka sama (z wyjątkiem liczb podnormalnych). –

+2

Przykład: '2^60' może być reprezentowany jako podwójny, natomiast' 2^60 (+/-) 1' nie może – aalku

13

Podwójny może być większy niż Long.MAX_VALUE. Jeśli wywołasz Math.ceil() na takiej wartości, możesz oczekiwać, że zwróci tę samą wartość. Jeśli jednak zwróci długi, wartość będzie niepoprawna.

+0

Wartości 'double', które są większe niż' Long.MAX_VALUE' mogą nie być dokładnie reprezentowane, więc wynik 'double' z' ceil (big_double) 'nie będzie miał znaczenia" big_double + 1 ". Więc nadal jest niepoprawny ... –

+0

@ CiprianTomoiaga masz rację, że nie będzie to big_double +1, ponieważ byłoby to big_double. Każda wartość, która jest zbyt duża, aby mogła być reprezentowana jako "długa", nie ma części ułamkowej. –