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ò.

È stato utile?

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

}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top