Ciao a tutti,
apro questa discussione perchè non ho ben chiaro la differenza tra i singoli AND e OR (& e |) e i doppi AND e OR (&& e ||).
Qualcuno mi saprebbe spiegare brevemente le differenze?
Grazie anticipatamente
Ciao a tutti,
apro questa discussione perchè non ho ben chiaro la differenza tra i singoli AND e OR (& e |) e i doppi AND e OR (&& e ||).
Qualcuno mi saprebbe spiegare brevemente le differenze?
Grazie anticipatamente
Sono i cosiddetti operatori bitwise e short-circuit.
Premesso che quelli singoli NON si dovrebbero usare al posto dei doppi, vediamo il perchè.
Gli operatori singoli operano sui bit: sono operatori che servono a fare "calcoli" tra bit, non sono operatori logici. Il risultato può sembrare uguale, ma non lo è, per un semplice motivo.
Gli operatori doppi offrono il short-circuit evaluation, mentre gli altri no. Cosa comporta? Vediamo un esempio:
Questo codice effettua per prima cosa una verifica sulla condizione "test". Se questa risulta falsa, il resto dell'espressione non viene valutato, quindi non viene preso in considerazione poichè sarebbe "inutile": FALSE messo in AND con qualunque altra cosa darà sempre FALSE. Il risultato dell'espressione è già noto, non serve verificare altro.codice:boolean test = false; if (test && fireTheWorld()) { // The world is on fire }
Nell'esempio, quindi, dato che la variabile booleana "test" è false, non viene eseguito il metodo "fireTheWorld()", non si entra nel corpo dell'isruzione if e si passa oltre.
Questo esempio:
è decisamente diverso: viene valutata prima la condizione "test" e successivamente, qualunque sia il risultato della valutazione, viene valutato anche fireTheWorld(). Con la conseguenza che, sebbene il risultato dell'espressione totale sia comunque FALSE, il metodo "fireTheWorld()" viene comunque invocato... ed il mondo va a fuoco nonostante le nostre buone intenzioni. Non si entra, comunque, nel corpo dell'if, ma il metodo viene invocato.codice:boolean test = false; if (test & fireTheWorld()) { // The world is on fire }
Un esempio più numerico:
La prima if è corretta: essendo che b è uguale a 0, la seconda parte (che effettua una divisione) non viene valutata, quindi non viene eseguita.codice:int a = 9; int b = 0; if ((b != 0) && (a / b > 1)) { // <<-- corretto! // a e b non sono uguali } if ((b != 0) & (a / b > 1)) { // <<-- sbagliato! // a e b non sono uguali }
La seconda if è sbagliata: viene verificato che b è uguale a zero, ma ciò nonostante, la divisione successiva viene eseguita, sollevando un bell'errore di divisione per zero.
La stessa cosa si applica all'operatore ||
Ciao.![]()
"Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza
Grazie Lele sei stato esaustivo ma ti volevo chiedere ancora una cosa per OR sul suo funzionamento... nel senso che se ho:Originariamente inviato da LeleFT
Sono i cosiddetti operatori bitwise e short-circuit.
Premesso che quelli singoli NON si dovrebbero usare al posto dei doppi, vediamo il perchè.
Gli operatori singoli operano sui bit: sono operatori che servono a fare "calcoli" tra bit, non sono operatori logici. Il risultato può sembrare uguale, ma non lo è, per un semplice motivo.
Gli operatori doppi offrono il short-circuit evaluation, mentre gli altri no. Cosa comporta? Vediamo un esempio:
Questo codice effettua per prima cosa una verifica sulla condizione "test". Se questa risulta falsa, il resto dell'espressione non viene valutato, quindi non viene preso in considerazione poichè sarebbe "inutile": FALSE messo in AND con qualunque altra cosa darà sempre FALSE. Il risultato dell'espressione è già noto, non serve verificare altro.codice:boolean test = false; if (test && fireTheWorld()) { // The world is on fire }
Nell'esempio, quindi, dato che la variabile booleana "test" è false, non viene eseguito il metodo "fireTheWorld()", non si entra nel corpo dell'isruzione if e si passa oltre.
Questo esempio:
è decisamente diverso: viene valutata prima la condizione "test" e successivamente, qualunque sia il risultato della valutazione, viene valutato anche fireTheWorld(). Con la conseguenza che, sebbene il risultato dell'espressione totale sia comunque FALSE, il metodo "fireTheWorld()" viene comunque invocato... ed il mondo va a fuoco nonostante le nostre buone intenzioni. Non si entra, comunque, nel corpo dell'if, ma il metodo viene invocato.codice:boolean test = false; if (test & fireTheWorld()) { // The world is on fire }
Un esempio più numerico:
La prima if è corretta: essendo che b è uguale a 0, la seconda parte (che effettua una divisione) non viene valutata, quindi non viene eseguita.codice:int a = 9; int b = 0; if ((b != 0) && (a / b > 1)) { // <<-- corretto! // a e b non sono uguali } if ((b != 0) & (a / b > 1)) { // <<-- sbagliato! // a e b non sono uguali }
La seconda if è sbagliata: viene verificato che b è uguale a zero, ma ciò nonostante, la divisione successiva viene eseguita, sollevando un bell'errore di divisione per zero.
La stessa cosa si applica all'operatore ||
Ciao.![]()
Non dovrebbe verificare lo stesso entrambi i criteri? Mi spiego meglio se da come hai detto te con || dovrebbe verifica la prima condizione è true verifica lo stesso anche la seconda? Ma in questo caso che cosa fa dove ho una condizione a true e l'altra a false?codice:int b = 0; int c = 1; if(b == 0 || c == 2){ istruzione }
Invece in questo caso che la prima è già a false dovrebbe verificare anche la seconda condizione? Anche perchè a sto punto si trasformerebbe in && non credi?codice:int b = 0; int c = 1; if(b == 1 || c == 2){ istruzione }
Poi mi sbaglio....
Grazie in anticipo....
Per l'OR vale lo stesso identico ragionamento, ma basato sul significato di OR:
In questo caso, il metodo non viene richiamato perchè l'espressione è già vera dopo la prima valutazione.codice:boolean test = true; if (test || metodo()) { ... }
In questo caso, al contrario, viene eseguito anche il metodo, nonostante il valore dell'espressione sia già chiaro dopo la prima valutazione.codice:boolean test = true; if (test | metodo()) { ... }
Ciao.![]()
"Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza
Ok grazie della spiegazione, ma a sto punto mi verrebbe da dire che non cè differenza tra il && e il ||..... o sbaglio?Originariamente inviato da LeleFT
Per l'OR vale lo stesso identico ragionamento, ma basato sul significato di OR:
In questo caso, il metodo non viene richiamato perchè l'espressione è già vera dopo la prima valutazione.codice:boolean test = true; if (test || metodo()) { ... }
In questo caso, al contrario, viene eseguito anche il metodo, nonostante il valore dell'espressione sia già chiaro dopo la prima valutazione.codice:boolean test = true; if (test | metodo()) { ... }
Ciao.![]()
Grazie anticipatamente
Eh?Originariamente inviato da manublack
Ok grazie della spiegazione, ma a sto punto mi verrebbe da dire che non cè differenza tra il && e il ||..... o sbaglio?
Grazie anticipatamente
Cioè, secondo te un OR e un AND sono la stessa cosa?
O non ho capito io la domanda...codice:boolean a = true; boolean b = false; System.out.println(a && b); // false System.out.println(a || b); // true System.out.println(a && a); // true System.out.println(a || a); // true System.out.println(b && b); // false System.out.println(b || b); // false
Ciao.![]()
"Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza
Originariamente inviato da LeleFT
Eh?
Cioè, secondo te un OR e un AND sono la stessa cosa?
O non ho capito io la domanda...codice:boolean a = true; boolean b = false; System.out.println(a && b); // false System.out.println(a || b); // true System.out.println(a && a); // true System.out.println(a || a); // true System.out.println(b && b); // false System.out.println(b || b); // false
Ciao.![]()
Scusa hai ragione mi sono spiegato male, nel senso che ti faccio un esempio.... Se io scrivo:
Cioè con il doppio OR (||) la seconda condizione mi viene eseguita lo stesso... Come mai?codice:boolean a = false; boolean b = true; System.out.println(a && b); // false System.out.println(a || b); // true System.out.println(a & b); // false System.out.println(a | b); // true
Perchè, come detto, la valutazione si ferma non appena il risultato può essere già garantito. Se il primo termine è false non posso sapere se più avanti ne troverò uno a true. Al contrario, se il primo è già true, non serve che vada avanti a valutare tutti gli altri. O meglio... si ferma al primo true che incontra. Prova questo esempio:Originariamente inviato da manublack
Cioè con il doppio OR (||) la seconda condizione mi viene eseguita lo stesso... Come mai?
Ciao.codice:private static boolean valuta(int i, boolean valore) { System.out.println("Valuto " + i + ": " + valore); return valore; } public static void main(String[] args) { System.out.println("Short-circuit OR ( || ): "); System.out.println(valuta(0, false) || valuta(1, true) || valuta(2, false) || valuta(3, false)); System.out.println("\n\n"); System.out.println("Bitwise OR ( | ): "); System.out.println(valuta(0, false) | valuta(1, true) | valuta(2, false) | valuta(3, false)); }![]()
"Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza
Originariamente inviato da LeleFT
Perchè, come detto, la valutazione si ferma non appena il risultato può essere già garantito. Se il primo termine è false non posso sapere se più avanti ne troverò uno a true. Al contrario, se il primo è già true, non serve che vada avanti a valutare tutti gli altri. O meglio... si ferma al primo true che incontra. Prova questo esempio:
Ciao.codice:private static boolean valuta(int i, boolean valore) { System.out.println("Valuto " + i + ": " + valore); return valore; } public static void main(String[] args) { System.out.println("Short-circuit OR ( || ): "); System.out.println(valuta(0, false) || valuta(1, true) || valuta(2, false) || valuta(3, false)); System.out.println("\n\n"); System.out.println("Bitwise OR ( | ): "); System.out.println(valuta(0, false) | valuta(1, true) | valuta(2, false) | valuta(3, false)); }![]()
Provato.....
Il risultato dell'esempio che mi hai dato è:
Short-circuit OR ( || ):
Valuto 0: false
Valuto 1: true
true
Bitwise OR ( | ):
Valuto 0: false
Valuto 1: true
Valuto 2: false
Valuto 3: false
true
Alla Fine nel Short-circuit è stato eseguito anche la seconda condizione anche se nel primo caso è false......
Ed è corretto. La valutazione di un OR non può fermarsi al primo false, può fermarsi solo al primo TRUE.Originariamente inviato da manublack
Alla Fine nel Short-circuit è stato eseguito anche la seconda condizione anche se nel primo caso è false......
Mi sa che ti mancano delle nozioni fondamentali sulle tabelle di verità relative agli OR e agli AND:
Un'espressione tra operandi in AND è FALSE se almeno uno degli operandi è FALSE.
Ergo, con un AND mi fermo al primo FALSE che trovo.
E' false se almeno uno dei vari opI è FALSEcodice:op1 AND op2 AND op3 AND ... AND opN
Un'espressione tra operandi in OR è TRUE se almeno uno degli operandi è TRUE.
Ergo, con un OR mi fermo al primo TRUE che trovo.
E' true se almeno uno dei vari opI è TRUEcodice:op1 OR op2 OR op3 OR ... OR opN
Ti è chiaro questo concetto?
Ciao.![]()
"Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza