2010-03-04 3 views
60

Ho codice per calcolare la differenza percentuale tra 2 numeri - (oldNum - newNum)/oldNum * 100; - dove entrambi i numeri sono double s. Mi aspettavo di dover aggiungere una sorta di controllo/gestione delle eccezioni nel caso oldNum sia 0. Tuttavia, quando ho eseguito un test con valori di 0.0 sia oldNum che newNum, l'esecuzione è continuata come se nulla fosse accaduto e non è stato generato alcun errore. L'esecuzione di questo codice con int s causerebbe sicuramente un'eccezione di divisione per zero aritmetica. Perché Java lo ignora quando si tratta di double s?Perché Java non lancia un'eccezione quando si divide per 0,0?

+4

Buona domanda: l'incoerenza tra numero intero e comportamento doppio aggiunge confusione e problemi. –

+2

possibile duplicato di [Perché la divisione per zero con numeri in virgola mobile (o precisione doppia) non genera java.lang.ArithmeticException:/per zero in Java] (http://stackoverflow.com/questions/12954193/why-does- division-by-zero-with-floating-point-or-double-precision-numbers-not) – Raedwald

+2

@Raedwald - considerando che questa domanda è stata pubblicata 2 anni e mezzo prima di quella che hai collegato, direi che la domanda è (possibile) duplicato di questo :) – froadie

risposta

42

Il risultato della divisione per zero è, matematicamente parlando, indefinito, che può essere espresso con un galleggiante/doppia (come NaN - non un numero), non è, però, sbagliato in ogni senso fondamentale.

Poiché un intero deve contenere un valore numerico specifico, è necessario generare un errore sulla divisione per zero quando si tratta di essi.

+6

Esattamente. Questo è definito nella specifica del linguaggio Java qui: http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.2.3 –

+1

Ho provato a emettere il risultato, ed è un valore NaN. Ciò significa che gli Ints non possono contenere NaN? – froadie

+1

ma questo è il caso di '0.0/0.0' che è NaN. –

4

Il modo in cui un doppio è memorizzato è molto diverso da un int. Vedere http://firstclassthoughts.co.uk/java/traps/java_double_traps.html per una spiegazione più dettagliata su come Java gestisce i calcoli doppi. Dovresti anche leggere i numeri in virgola mobile, in particolare il concetto di Not a Number (NaN).

Se sei interessato a saperne di più sulla rappresentazione in virgola mobile, ti consiglio di leggere this document (formato Word, mi dispiace). Scava nella rappresentazione binaria dei numeri, che può essere utile per la vostra comprensione.

101

float e double tipi di Java, come praticamente qualsiasi altra lingua là fuori (e praticamente qualsiasi unità hardware FP), implementano lo standard IEEE 754 per matematica in virgola mobile, che impone la divisione per zero per restituire un valore speciale "infinito" . Lanciare un'eccezione in realtà violerebbe quello standard.

L'aritmetica dei numeri interi (implementata come rappresentazione two's complement in Java e nella maggior parte degli altri linguaggi e hardware) è diversa e non ha valori infinito o NaN speciali, pertanto l'eccezione di lancio è un comportamento utile.

+3

La risposta corretta a questa domanda dovrebbe essere questa. Dovevo sapere perché 'float' e' double' non causano eccezioni. Grazie. –

+1

Questa dovrebbe essere la risposta corretta contrassegnata.La risposta correntemente contrassegnata come corretta non risponde alla domanda, né indica chiaramente che Java sta seguendo IEEE 754. – Necrototem

3

se gli sviluppatori Java a conoscenza del tipo primitivo doppio e Double di classe, mentre si fa aritmetica in virgola mobile che non prestano sufficiente attenzione a Double.INFINITY, NaN, -0.0 e le altre norme che regolano i calcoli aritmetici che li coinvolgono.

La semplice risposta a questa domanda è che non getterà ArithmeticException e restituirà Double.INFINITY. Si noti inoltre che il confronto x == Double.NaN viene sempre valutato su false, anche se x è uno NaN.

Per verificare se x è un NaN, è necessario utilizzare la chiamata al metodo Double.isNaN(x) per verificare se il numero dato è NaN o meno. Questo è molto vicino a NULL in SQL.

Potrebbe esserti utile.

1

quando diviso per zero (0 o 0,00)

  1. Se si divide doppia da 0, JVM mostrerà Infinity.

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

    Console: Infinity

  2. Se si divide int da 0, allora JVM getterà aritmetica Eccezione.

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

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

  3. Ma se dividiamo int da 0.0, quindi JVM mostrerà Infinity:

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

    Console: Infinity

Questo perché JVM digiterà automaticamente cast int per raddoppiare, quindi otteniamo infinito invece di ArithmeticException.