Come scrivere la seguente espressione booleana?
-
11-09-2019 - |
Domanda
Ho tre valori booleani A, B e C. ho bisogno di scrivere un'istruzione IF, che sarà eseguita se e solo se non più di uno di questi valori è vero. In altre parole, qui è la tabella di verità:
A | B | C | Result
---+---+---+--------
0 | 0 | 0 | 1
0 | 0 | 1 | 1
0 | 1 | 0 | 1
0 | 1 | 1 | 0
1 | 0 | 0 | 1
1 | 0 | 1 | 0
1 | 1 | 0 | 0
1 | 1 | 1 | 0
Qual è il modo migliore per scrivere questo? So che posso elencare tutte le possibilità, ma che sembra ... troppo prolisso. : P
Aggiunto: Appena avuto una sola idea:
! (A && B) &&! (B && C) &&! (A && C)
Questa verifica che non esistono due valori sono impostati. Il suggerimento circa le somme è OK pure. Ancora più leggibile forse ...
(A 1: 0) + (B 1: 0) + (C 1: 0) <= 1
P.S. Questo è per il codice di produzione, quindi ho intenzione di più per migliorare la leggibilità del codice di prestazioni.
Aggiunto 2: risposta già accettato, ma per i curiosi - è C #. :) La domanda è praticamente indipendente dal linguaggio però.
Soluzione
come circa trattandoli come intero 1 e 0, e controllando che la loro somma è uguale a 1?
Modifica :
ora che sappiamo che si tratta di C # .NET, penso che la soluzione più leggibile apparirebbe un po 'come
public static class Extensions
{
public static int ToInt(this bool b)
{
return b ? 1 : 0;
}
}
È possibile che questo nascosto in una libreria di classi (? Appcode) dove non c'è bisogno di vederlo, ma può facilmente accedervi (Ctrl + clic in R #, per esempio) e quindi l'attuazione saranno semplicemente:
public bool noMoreThanOne(params bool[] bools)
{
return bools.ToList().Sum(b => b.ToInt()) <= 1;
}
...
bool check = noMoreThanOne(true, true, false, any, amount, of, bools);
Altri suggerimenti
È shold familiarizzare con Karnaugh Maps . Concetto è più spesso applicata all'elettronica, ma è molto utile anche qui. E 'molto facile (pensava Wikipedia spiegazione ha un aspetto a lungo - è approfondita).
(A XOR B XOR C) o meno (A o B o C)
Modifica:. Come sottolineato da Vilx, questo non è giusto
Se A e B sono entrambe 1, e C è 0, A XOR B sarà 0, il risultato complessivo sarà 0.
Come su: NOT (A e B) E NON (A e C) e NOT (B e C)
Se si attiva la logica in giro, si desidera che la condizione di essere falsa se si dispone di una qualsiasi coppia di booleani che sono sia vero:
if (! ((a && b) || (a && c) || (b && c))) { ... }
Per qualcosa di completamente diverso, si può mettere la booleani in un array e contare quanti valori vero che ci sono:
if ((new bool[] { a, b, c }).Where(x => x).Count() <= 1) { ... }
mi piacerebbe andare per la massima manutenibilità e la leggibilità.
static bool ZeroOrOneAreTrue(params bool[] bools)
{
return NumThatAreTrue(bools) <= 1;
}
static int NumThatAreTrue(params bool[] bools)
{
return bools.Where(b => b).Count();
}
Ci sono molte risposte qui, ma ho un altro!
a ^ b ^ c ^ (a == b && b == c)
Un modo generale di trovare un'espressione booleana minima per una determinata tabella di verità è quella di utilizzare una mappa di Karnaugh:
http://babbage.cs.qc.edu/courses/Minimize/
Ci sono diversi minimi online sul web. L'uno qui (legato al dall'articolo, è in tedesco, però) trova la seguente espressione:
(! A &&! B) || (! A &&! C) || (! B &&! C)
Se si sta andando per la leggibilità del codice, anche se, probabilmente andare con l'idea di "sum <= 1". Fare attenzione che non tutte le lingue garantiscono quel falso == 0 e vero == 1 - ma probabilmente siete a conoscenza di questo dato che hai preso cura di esso nella vostra soluzione.
Il buon vecchio' logica:
+ = OR
. = AND
R = Abar.Bbar.Cbar + Abar.Bbar.C + Abar.B.Cbar + A.Bbar.Cbar
= Abar.Bbar.(Cbar + C) + Abar.B.Cbar + A.Bbar.Cbar
= Abar.Bbar + Abar.B.Cbar + A.Bbar.Cbar
= Abar.Bbar + CBar(A XOR B)
= NOT(A OR B) OR (NOT C AND (A XOR B))
prendere il suggerimento e semplificare ulteriormente se si desidera.
E sì, ottenere la vostra auto familiarità con mappe di Karnaugh
Dipende se si vuole qualcosa in cui è facile capire che cosa si sta cercando di fare, o qualcosa che è logicamente semplice come può essere. Altre persone sono distacco risposte logicamente semplici, quindi ecco quello in cui è più chiaro quello che sta succedendo (e quale sarà il risultato per gli ingressi diversi):
def only1st(a, b, c):
return a and not b and not c
if only1st(a, b, c) or only1st(b, a, c) or only1st(c, a, b):
print "Yes"
else:
print "No"
Mi piace la soluzione di più, ma qui è un trucco per farlo con campi di bit così.
inline bool OnlyOneBitSet(int x)
{
// removes the leftmost bit, if zero, there was only one set.
return x & (x-1) == 0;
}
// macro for int conversion
#define BOOLASINT(x) ((x)?1:0)
// turn bools a, b, c into the bit field cba
int i = (BOOLASINT(a) << 0) | BOOLASINT(b) << 1 | BOOLASINT(c) << 2;
if (OnlyOneBitSet(i)) { /* tada */ }
Codice dimostrazione della soluzione d's:
int total=0;
if (A) total++;
if (B) total++;
if (C) total++;
if (total<=1) // iff no more than one is true.
{
// execute
}