2010-03-04 10 views
60

Mam kod do obliczenia różnicy procentowej między 2 liczbami - (oldNum - newNum)/oldNum * 100; - gdzie obie liczby są double s. Spodziewałem się, że będę musiał dodać pewien rodzaj sprawdzania/obsługi wyjątków w przypadku, gdy oldNum wynosi 0. Jednakże, kiedy wykonałem test z wartościami 0.0 dla zarówno oldNum, jak i newNum, wykonanie było kontynuowane tak, jakby nic się nie stało i nie zgłoszono żadnego błędu. Uruchomienie tego kodu z int s z pewnością spowoduje arytmetyczne wyjątki dzielenia przez zero. Dlaczego Java ignoruje je, jeśli chodzi o double s?Dlaczego Java nie zgłasza wyjątku przy dzieleniu przez 0,0?

+4

Dobre pytanie - niespójność między liczbą całkowitą a podwójnym zachowaniem powoduje zamieszanie i problemy. –

+2

możliwy duplikat [Dlaczego dzielenie przez zero liczb zmiennoprzecinkowych (lub podwójnej precyzji) nie powoduje wyrzucenia java.lang.ArithmeticException:/przez zero w Javie] (http://stackoverflow.com/questions/12954193/why-does- dzielenie przez zero z liczbami zmiennoprzecinkowymi lub podwójnymi liczbami precyzyjnymi-nie) – Raedwald

+2

@Raedwald - biorąc pod uwagę, że to pytanie zostało opublikowane 2 1/2 roku przed tym, które łączysz, powiedziałbym, że to pytanie (możliwe) duplikat tego :) – froadie

Odpowiedz

42

Wynik dzielenia przez zero, jest matematycznie biorąc, niezdefiniowany, co może być wyrażone w pływak/podwójnym (tak jak NaN - nie liczba), nie jest jednak tak w każdym podstawowym znaczeniu.

Jako liczba całkowita musi zawierać określoną wartość liczbową, błąd musi zostać zgłoszony w przypadku dzielenia przez zero przy ich rozwiązywaniu.

+6

Dokładnie. Jest to zdefiniowane w Specyfikacji Języka Java tutaj: http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.2.3 –

+1

Próbowałem wyprowadzić wynik i jest to wartość NaN. Czy to oznacza, że ​​ints nie może utrzymać NaN? – froadie

+1

, ale tak jest w przypadku "0.0/0.0", który jest NaN. –

4

Sposób przechowywania podwójnego jest zupełnie inny niż int. Bardziej szczegółowe wyjaśnienie, w jaki sposób Java obsługuje podwójne obliczenia, można znaleźć w artykule http://firstclassthoughts.co.uk/java/traps/java_double_traps.html. Powinieneś również zapoznać się z numerami zmiennoprzecinkowymi, w szczególności z pojęciem Not a Number (NaN).

Jeśli chcesz dowiedzieć się więcej o reprezentacji zmiennoprzecinkowej, radzę przeczytać: this document (format Word, przepraszam). Zagłębia się w binarną reprezentację liczb, która może być pomocna dla twojego zrozumienia.

101

Java float i double rodzaje, jak prawie każdy inny język tam (i prawie każda jednostka sprzętowa FP), wdrożenie standardu z IEEE 754 dla matematyki zmiennoprzecinkowej, który nakłada obowiązek dzielenie przez zero zwrócić szczególną wartość „Infinity” . Rzucenie wyjątku naruszyłoby ten standard.

Arytmetyka liczb całkowitych (zaimplementowana jako reprezentacja przez Java i większość innych języków i sprzętu) jest inna i nie ma specjalnych wartości nieskończoności lub NaN, w związku z czym zalecane są wyjątki wyrzucania.

+3

Właściwa odpowiedź na to pytanie powinna być taka. Musiałem wiedzieć, dlaczego 'float' i' double' nie powodują wyjątków. Dzięki. –

+1

Powinno to być zaznaczona prawidłowa odpowiedź.Odpowiedź obecnie oznaczona jako poprawna nie odpowiada na pytanie, ani nie wyjaśnia, że ​​Java przestrzega IEEE 754. – Necrototem

3

Choć programistów Java wiedzieć o podwójnej prymitywnego rodzaju i Double klasie, robiąc arytmetyki zmiennoprzecinkowej nie zwracają wystarczającej uwagi do Double.INFINITY, NaN, -0.0 i innych zasad, które rządzą ich udziałem obliczeń arytmetycznych.

Najprostszą odpowiedzią na to pytanie jest to, że nie wyrzuci on ArithmeticException i zwróci Double.INFINITY. Należy również zauważyć, że porównanie x == Double.NaN zawsze ocenia się na false, nawet jeśli x sam w sobie jest NaN.

Aby sprawdzić, czy x jest NaN, należy użyć wywołania metody Double.isNaN(x), aby sprawdzić, czy podana liczba to NaN, czy nie. Jest to bardzo zbliżone do NULL w SQL.

Może to być pomocne.

1

Kiedy dzieli się przez zero (0 LUB 0.00)

  1. Jeśli podzielić dwukrotnie przez 0, JVM pokaże nieskończoność.

    public static void main(String [] args){ double a=10.00; System.out.println(a/0); }

    konsoli: Infinity

  2. Po podzieleniu przez int 0, to JVM rzuci arytmetyczne wyjątek.

    public static void main(String [] args){ int a=10; System.out.println(a/0); }

    konsoli: Exception in thread "main" java.lang.ArithmeticException:/by zero

  3. Ale jeśli dzielimy int przez 0,0, a następnie JVM pokaże nieskończoność:

    public static void main(String [] args){ int a=10; System.out.println(a/0.0); }

    konsoli: Infinity

Dzieje się tak, ponieważ JVM automatycznie wypisze int, aby podwoić, więc otrzymamy nieskończoność zamiast wyjątku ArithmeticException.

Powiązane problemy