7

Ho la seguente domanda:Perché JDK usa lo spostamento invece di moltiplicare/dividere?

Se viene chiesto se utilizzare uno spostamento rispetto a un moltiplicare o dividere, ad esempio la risposta sarebbe, lasciare ottimizzare la JVM.

Esempio qui: is-shifting-bits-faster-than-multiplying

Ora stavo guardando la fonte JDK, per esempio Priority Queue e il codice utilizza spostando solo sia per moltiplicazione e divisione (firmato e non firmato).

dando per scontato che il posto in SO è la risposta valida Mi chiedevo perché in JDK preferiscono farlo spostando?

E 'un po' sottili dettagli estranei a prestazioni? Sospetto che debba avere qualcosa a che fare con la moltiplicazione e la divisione di over/underflow ma non ne sono sicuro.

Qualcuno ha un'idea? I problemi di overflow sono gestiti meglio utilizzando lo spostamento? O è solo una questione di gusti?

risposta

6

penso lo fanno in questo esempio specifico per utilizzare il bit del segno. Java non ha tipi non firmati, quindi non è possibile emulare a >>> 1 con a /= 2 per i numeri che utilizzano il bit più significativo. Nota come il codice utilizza solo >>> durante l'esempio. Sono ragionevolmente certo che questo serva a sfruttare appieno l'intera gamma di bit.

+0

Quindi non è possibile scrivere codice senza bug senza operatore di cambio per subdoli problemi come questo? – Cratylus

+0

@ user384706 Certo che puoi: un semplice operatore ternario qua e là potrebbe aiutarti a fare il trucco. Tuttavia, l'efficienza sta andando a soffrire. – dasblinkenlight

+0

Sarebbe possibile mostrare un esempio di questo? Sarei interessato a conoscere – Cratylus

2

È più una questione di gusti. Alcune persone sono così abituate alle operazioni binarie che sono più native per loro (personalmente uso anche questo codice che sto scrivendo per me stesso). Tuttavia dal punto di vista delle prestazioni i due si comportano allo stesso modo (l'ottimizzazione avviene in fase di compilazione, quindi l'uso dei turni migliorerà il tempo di compilazione, ma con una frazione minore e si può trascurare).

EDIT E come spesso accade c'è qualcosa di nuovo ho imparato da ogni risposta dò: considerare this. Dimostra perché la divisione per due non può sempre essere ottimizzata per il cambio. Quindi il mio commento sopra è quasi completamente sbagliato, a patto che java non ha tipi non firmati.

+1

Più in generale: il JIT in java può sostituire la divisione con una potenza di 2 con turni se può garantire che i numeri siano positivi.In caso contrario, abbiamo bisogno di una routine più complessa (che in pratica si riduce a 3 turni e un add per la versione gratuita del ramo o una diramazione e aggiungi + shift) – Voo

3

Alcuni validi motivi per preferire lo spostamento in Java:

  • Se c'è una possibilità che si può essere in esecuzione in un ambiente non ottimizzato e non è possibile garantire che il compilatore JIT farà la ottimizzazione necessaria per te. Questo è probabilmente raro al giorno d'oggi, ma potrebbe ancora accadere in alcune circostanze.
  • Se siete veramente facendo manipolazioni bit piuttosto che operazioni numeriche - è più evidente nel codice sorgente di utilizzare turni direttamente
  • Se volete operazioni senza segno (ad esempio, si può facilmente fare turni non firmati, ma divisioni non firmate)
+0

Suppongo che la ragione 3 sia la ragione per cui, per esempio, nell'implementazione della coda di priorità preferiscono cambiare? – Cratylus

5

A parte lo spostamento più veloce della divisione sulla maggior parte dei sistemi. Il >>> esegue un'operazione non firmata, che divisione non ha. per esempio. se si desidera il punto centrale di due valori, è necessario utilizzare >>> per evitare un overflow. (Vedi Arrays.binaryCerca per codice simile)

+0

Mi chiedevo perché parli di prestazioni nella tua prima frase. Non lo ottimizzerò comunque JVM? Questo è quello che ho capito dall'altro thread SO di cui ho parlato in OP – Cratylus

+1

La divisione non è equivalente allo spostamento se gli input sono negativi, e la JVM non può sempre dimostrare che gli input non sono negativi, nel qual caso deve prendere il colpo della divisione. –

+0

@LouisWasserman: Quindi stai dicendo che dobbiamo sempre usare gli operatori di turno perché JVM non ottimizzerà sempre come ci aspettiamo? Nel thread SO a cui mi sono collegato, questo non è stato menzionato credo – Cratylus

Problemi correlati