Quando è appropriato utilizzare un operatore bit a bit in un'espressione condizionale?

15

In primo luogo, alcuni background: Sono un insegnante di informatica IT e sto cercando di presentare gli operatori booleani di java alla mia classe di decima classe. Il mio insegnante-mentore ha esaminato un foglio di lavoro che ho preparato e ho commentato che avrei potuto lasciare che usassero solo un singolo & o | per indicare gli operatori, perché "fanno la stessa cosa".

Sono consapevole della differenza tra & e & & amp ;.
& è un operatore bit a bit destinato all'uso tra interi, per eseguire "bit-twiddling".
& & è un operatore condizionale destinato all'uso tra valori booleani.

Per dimostrare che questi operatori non sempre "fanno la stessa cosa", ho deciso di trovare un esempio in cui l'utilizzo del bit a bit tra valori booleani avrebbe comportato un errore. Ho trovato questo esempio

boolean bitwise;
boolean conditional;
int i=10, j=12;
bitwise = (i<j) | ((i=3) > 5); // value of i after oper: 3
System.out.println(bitwise+ " "+ i);
i=10; 
conditional = (i<j) || (i=3) > 5 ;  // value of i after oper: 10
System.out.println(conditional+ " "+ i);
i=10; 
bitwise = (i>j) & (i=3) > 5;   // value of i after oper: 3
System.out.println(bitwise+ " "+ i);
i=10; 
conditional = (i>j) && (i=3) > 5;  // value of i after oper: 10
System.out.println(conditional+ " "+ i);

Questo esempio mostra che se un valore deve essere modificato dalla seconda metà dell'espressione, ciò comporterebbe una differenza tra i risultati, poiché bitwise è un operatore ansioso, mentre il condizionale si comporta come un corto circuito (non valutare la seconda metà, se la prima metà è falsa nel caso di & & e vera nel caso di ||).

Ho un problema con questo esempio. Perché dovresti voler cambiare un valore nello stesso momento in cui esegui una comparazione? Non sembra un modo robusto per codificare. Sono sempre stato contrario a fare più operazioni su una singola riga nel mio codice di produzione. Sembra che qualcosa di un "cowboy codificante" senza coscienza per quanto riguarda la manutenibilità del suo codice farebbe. So che in alcuni domini il codice deve essere il più compatto possibile, ma sicuramente questa è una cattiva pratica in generale?

Posso spiegare la mia scelta di incoraggiare l'uso di & & e || oltre & e | perché questo è un accettato convenzione di codifica nell'ingegneria del software .

Ma qualcuno potrebbe darmi un esempio migliore, anche reale, di usare un operatore bit a bit in un'espressione condizionale?

    
posta Deerasha 14.04.2011 - 18:54
fonte

5 risposte

16

è appropriato quando si esegue un'operazione di mascheramento

if ((a & b) > 0) {...}

dove a e b sono numeri interi

|| e | e & & e & non sono intercambiabili

| e & non comparirà mai in un'espressione condizionale da solo (il punto del collegamento che hai incluso è che tali cose sono molto spesso errori)

EDIT: non discutere con il tuo mentore; anche se vinci, perdi. Invece, spiega che non vuoi confondere gli studenti mescolando operatori logici e operatori bit a bit nella stessa lezione. Potresti spiegare che se i = 3 e j = 2 allora i & j = 2, mentre i & & j è un errore. Tuttavia, la spiegazione più semplice è che stai insegnando agli operatori booleani (logici), quindi il lancio di equivalenti bit a bit per casi speciali è una distrazione dal punto principale della lezione. Non è necessario rendere il mentore "sbagliato" e non è necessario produrre contro-esempi. Il focus della lezione è sugli operatori booleani, non operatori bit a bit.

Come corollario, quando inizi a insegnare operatori bit a bit, non è necessario mostrare i casi speciali in cui + e - producono gli stessi risultati di & e |

    
risposta data 14.04.2011 - 19:13
fonte
11

Gli operatori non bit a bit && e || sono operatori di cortocircuito. In altre parole, con && , se LHS è falso, l'RHS non verrà mai valutato; con || se LHS è true, quindi l'RHS non verrà mai valutato. D'altra parte, gli operatori bit a bit & e | non hanno cortocircuito e valuteranno sempre sia LHS che RHS. Altrimenti, sono equivalenti in un'istruzione if .

L'unica volta che riesco a vedere il valore nell'usare gli operatori senza cortocircuito è se l'RHS ha qualche tipo di effetto collaterale desiderabile che si vuole che accada in tutti i casi. Non riesco a pensare ad un esempio specifico in cui vorresti questo, e non credo che sia una buona pratica, ma questa è la differenza.

    
risposta data 14.04.2011 - 19:34
fonte
7

La risposta filosofica generale è che l'uso di operatori bit a bit per operatori booleani è atipico e rende il codice più difficile da leggere. In pratica (per il codice che è in produzione), il codice più leggibile è più facile da mantenere e quindi più desiderabile.

Per un uso reale della necessità di operatori di cortocircuito, vedere casi come:

if (args.length > 0 && args[0] == 'test') ....

if (b != NULL && b.some_function()) ...

if (b == NULL || b.some_function()) ...

Questo tipo di operazioni si presenta frequentemente nel codice del mondo reale.

    
risposta data 14.04.2011 - 20:22
fonte
4

Utilizzerai operatori bit a bit se confronti le enumerazioni di Bitmask. Ad esempio, hai un'enumerazione di stati e un oggetto che può trovarsi in più di uno di questi stati. In questo caso, eseguirai un bit per bit o assegnerai più di uno stato al tuo oggetto.

ad esempio state = CONNECTED | IN_PROGRESS dove CONNECTED could be 0x00000001 e IN_PROGRESS 0x00000010

Per maggiori informazioni, consulta la documentazione relativa alle enumerazioni dei flag.

    
risposta data 14.04.2011 - 19:12
fonte
0

un esempio più semplice di errato:

int condA=1, condB=2;

if (condA!=0 && condB!=0) {
    // correct!
}
if ((condA & condB)!=0) {
    // never executed
}

qui ci sono due condizioni, entrambe sono non zero; ma il bit per bit & ha come risultato zero.

    
risposta data 14.04.2011 - 21:02
fonte

Leggi altre domande sui tag