2010-10-01 13 views
5

La differenza tra il numero intero si moltiplica (dimenticandosi temporaneamente della divisione) ancora a favore dello spostamento e, in tal caso, quanto è grande la differenza?Perché Java e C# hanno operatori di bitshifts?

Sembra semplicemente un'ottimizzazione di basso livello, anche se si desidera che il compilatore bytecode (C#/Java) o il jit non lo catturino nella maggior parte dei casi?

Nota: ho provato l'uscita compilato per C# (con GMCs Mono compilatore C# versione 2.6.7.0) e gli esempi si moltiplicano non ha utilizzato spostamento per moltiplicare anche quando moltiplicando per un multiplo di 2.

C# http://csharp.pastebin.com/hcrRnPrb

cil http://csharp.pastebin.com/0js9F2c1

PS Ho dimenticato come potrebbe essere utile usarlo su byte, ma ho ancora qualche problema a usarlo per Numbers.

+9

Moltiplica non è l'unico utilizzo degli operatori di bitshifts. – Cristian

+3

Talvolta gli operatori bitshift aumentano la chiarezza su una moltiplicazione equivalente. –

+2

Stai guardando l'IL, hai davvero bisogno di vedere il codice macchina dopo la compilazione JIT per verificare se il framework li sta ottimizzando correttamente. –

risposta

8

Hai ragione, se gli operatori di shift sono usati solo come alternativa per le moltiplicazioni, dovrebbe essere lasciato al compilatore.

Suppongo che trascurato applicazioni come:

  • crittografia/decrittografia calcolo
  • CRC
  • manipolazione bitmap (Graphics, serrature di database)
  • di compressione/decompressione
  • Impostazione dei dati per l'hardware registri
  • Cambia codifica

e molto altro ancora serve un po 'per l'implementazione efficiente senza codice nativo.

22

prima ragione:

A volte - la maggior parte delle volte - si vuole trattare un intero come un numero di . A volte anche se un intero è un modo conveniente per rappresentare un insieme di bit.

La moltiplicazione è un'operazione sui numeri.

Lo spostamento è un'operazione su un set di bit.

Che ci sia una relazione tra i risultati della moltiplicazione e i risultati dello spostamento non è particolarmente rilevante. Le operazioni sono logicamente diverse.

Seconda ragione:

C# e Java sono stati entrambi progettati per essere familiare agli sviluppatori C, anche se a un livello superficiale. Quindi gli idiomi comuni di C erano inclusi in C# e Java.

+0

C# e Java (in particolare il secondo) hanno rilasciato molte cose da c e C++. –

+0

Ancora più importante, sono curioso di sapere perché si vorrebbe rappresentare 2 byte come int se non vuole essere un numero. –

+0

@Roman: perché è possibile spostarlo (e altre operazioni) due volte con la stessa efficienza di quando si memorizzano due byte in variabili separate. –

12

Se volessi moltiplicare un numero per 4, scriverei * 4. Se il mio intento è di spostare a sinistra di alcuni bit 2 posizioni, scriverei .

Re la domanda:

Perché Java e C# hanno bitshifts operatori?

devo fare un sacco di lavoro sui dati binari, dove Non sto pensando di interi ecc - solo binario - e in quella zona si è del tutto logico da usare operatori di spostamento costante.

Certo, ho potuto tipo * 2 ecc, ma quello che realmente voglio fare è spostare i bit.

Questo è comune in un intervallo di aree in cui i byte sono importanti (ad esempio la programmazione grafica, la serializzazione, ecc.).

Inoltre, ci sono alcune sottigliezze delle operazioni di scorrimento dove non si vogliono che si comporti come un intero, in particolare quando si tratta con i bordi ... le regole di quello che succede quando hai lasciato-shift un po 'fuori dalla mappa, o bit di spostamento a destra in la mappa (-ve vs + ve ecc.) sono ben compresi ma critici. Allo stesso modo, il comportamento checked/unckecked della moltiplicazione dei numeri interi è talvolta molto importante.

0

Perché i progettisti di linguaggi hanno pensato che sarebbe stato bello averli.

Non è davvero importante che siano equivalenti ad altre opperazioni e che i compilatori siano abbastanza intelligenti da implementare le operazioni in modo efficiente. Se è lì che stiamo andando, non è necessario molto più di un macro assemblatore e un ottimo ottimizzatore del tempo di collegamento, magari su una VM con un garbage collector. Questi non sono gli obiettivi che i designer di linguaggio normalmente perseguono.

1

Quello che si sta chiedendo non è essenzialmente il motivo per cui ci sono operatori di bit in C#/Java, ma perché il compilatore javac non ottimizza le moltiplicazioni e le divisioni con le potenze di due in bitshift.

La reazione istintiva a questo è che la moltiplicazione e la divisione hanno semantica diversa dai bitshifts, quindi non mappa al 100% per sostituire le operazioni.

Inoltre, si è dimenticato il passaggio di compilazione aggiuntivo che si verifica nel JIT (HotSpot) in cui si verificano tutti i tipi di ulteriori ottimizzazioni. Non c'è francamente alcun bisogno di ottimizzare questo particolare passo, al contrario di C dove il codice è come il compilatore lo genera.

0

Ad esempio, il programma potrebbe utilizzare qualcosa come le maschere di bit. In tal caso l'operazione bitshift è una necessità. O se stai solo risolvendo un compito strano che richiede la codifica degli stati in un modo specificato.

Guarda questo tutorial - la maggior parte dei campioni proviene da problemi di matematica. Se stai semplicemente creando un sito o un'applicazione GUI, probabilmente non hai bisogno di spostarti, ma a volte lo fai davvero ...

+0

Sono d'accordo sul fatto che il bithifting ha la sua area in cui rendono il codice più facile da leggere/scrivere bur che potresti ottenere senza di loro e semplicemente usare * 2^n o/2^n invece di <> n. Quindi non sono necessari, ma è bello avere –

+2

@Rune FS, -1 >> 1 non è uguale a -1/2, indipendentemente dall'estensione del segno. Riscrivere le operazioni di spostamento usando solo operatori matematici è in realtà piuttosto laborioso. –

+0

@Jon ti sei perso il punto in cui non sono necessari, ma possono essere riscritti (e i segni non hanno senso quando si parla di pattern di bit poiché essi inferiscono una specifica interpretazione del pattern che non fa parte del pattern stesso. più schemi di bit che in un dato contesto rappresentano -1 e Tutti rappresentano un numero intero positivo in diversi contesti e parte di un file crittografato in un altro contesto –

0

Così puoi spostare i bit a destra e a sinistra. Quello che vuoi che quei bit e le loro operazioni di spostamento rappresentino è interamente a te.

+0

@ Rune FS ... O! uomo ... ah ah ah ... è stato un errore esilarante. Grazie per la correzione. – explorer

0

Oltre agli altri motivi qui, ci sono molti casi in cui potrebbe essere necessario spostare (o altre operazioni di bit) per interfacciarsi con una libreria di terze parti o un'applicazione remota su una rete.

Problemi correlati