Divisione semplice in Java: si tratta di un bug o di una funzionalità?

Sto provando questo semplice calcolo in un’applicazione Java:

System.out.println("b=" + (1 - 7/10)); 

Ovviamente voglio b=0.3 per l’output ma ecco cosa ottengo b=1 .

Che cosa?! Perché succede?

Se faccio:

 System.out.println("b=" + (1 - 0.7)); 

Ottengo il risultato giusto che è b=0.3 .

Cosa c’è che non va qui?

Stai usando la divisione intera.

Prova 7.0/10 invece.

Hai utilizzato numeri interi nell’espressione 7/10 e il numero intero 7 diviso per il numero intero 10 è zero.

Quello che ti aspetti è la divisione in virgola mobile. Una delle seguenti azioni valuterà il modo in cui ti aspettavi:

 7.0 / 10 7 / 10.0 7.0 / 10.0 7 / (double) 10 

Si prega di non prendere questo come una risposta alla domanda. Non lo è, ma un consiglio relativo allo sfruttamento della differenza di int e float. Avrei messo questo sotto un commento tranne per il fatto che la casella di risposta mi consente di formattare questo commento.

Questa funzione è stata utilizzata in ogni linguaggio di programmazione rispettabile dai tempi di Fortran (o anche prima) – Devo confessare che una volta ero un programmatore di tabs perforate Fortran e Cobol.

Ad esempio, la divisione intera di 10/3 restituisce il valore intero 3 poiché un numero intero non ha la possibilità di mantenere il residuo frazionario 3333 …

Uno dei modi in cui noi (vecchi programmatori antichi) usavamo questa funzione è il controllo del ciclo.

Diciamo che desideriamo stampare una serie di 1000 stringhe, ma desideriamo inserire un’interruzione di riga dopo ogni 15a stringa, per inserire alcuni caratteri graziosi alla fine della riga e all’inizio della riga successiva. Lo sfruttiamo, dato che l’intero k è la posizione di una stringa in quell’array.

 int(k/15)*15 == k 

è vero solo quando k è divisibile per 15, un’occorrenza ad una frequenza di ogni 15 ° cella. Il che è simile a ciò che il mio amico ha detto a proposito del fatto che la guardia del nonno è accurata due volte al giorno.

 int(1/15) = 0 -> int(1/15)*15 = 0 int(2/15) = 0 -> int(2/15)*15 = 0 ... int(14/15) = 0 -> int(14/15)*15 = 0 int(15/15) = 1 -> int(15/15)*15 = 15 int(16/15) = 1 -> int(16/15)*15 = 15 int(17/15) = 1 -> int(17/15)*15 = 15 ... int(29/15) = 1 -> int(29/15)*15 = 15 int(30/15) = 2 -> int(30/15)*15 = 30 

Pertanto, il ciclo,

 leftPrettyfy(); for(int k=0; k 

Modificando k in modo fantasioso nel ciclo, potremmo stampare una stampa triangular

 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 

Questo per dimostrare che, se consideri questo un bug, questo " bug " è una funzionalità utile che non vorremmo rimuovere da nessuno dei vari linguaggi che abbiamo usato fino ad ora.

Trovo che gli identificatori di lettere siano più leggibili e più indicativi del tipo analizzato:

 1 - 7f / 10 1 - 7 / 10f 

o:

 1 - 7d / 10 1 - 7 / 10d 

Nel mio caso stavo facendo questo:

 double a = (double) (MAX_BANDWIDTH_SHARED_MB/(qCount+1)); 

Invece del “corretto”:

 double a = (double)MAX_BANDWIDTH_SHARED_MB/(qCount+1); 

Prendi attenzione con le parentesi!