1

我有三个布尔值 A、B 和 C。我需要编写一个 IF 语句,当且仅当这些值中只有一个为真时才会执行。换句话说,这是真值表:

 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

写这个的最好方法是什么?我知道我可以列举所有可能性,但这似乎……太冗长了。:P

补充:只有一个想法:

!(A && B) && !(B && C) && !(A && C)

这将检查没有设置两个值。关于总和的建议也可以。也许更具可读性...

(A?1:0) + (B?1:0) + (C?1:0) <= 1

PS这是用于生产代码的,所以我更关注代码的可读性而不是性能。

添加 2:已经接受的答案,但对于好奇的人 - 它是 C#。:) 这个问题几乎与语言无关。

4

11 回答 11

11

如何将它们视为整数 1 和 0,并检查它们的总和是否等于 1?

编辑

现在我们知道它是 c#.net,我认为最易读的解决方案看起来有点像

public static class Extensions
{
    public static int ToInt(this bool b)
    {
        return b ? 1 : 0;
    }
}

上面隐藏在一个类库(appcode?)中,我们不必看到它,但可以轻松访问它(例如,在 r# 中按 ctrl+click),然后实现将是:

public bool noMoreThanOne(params bool[] bools) 
{ 
    return bools.ToList().Sum(b => b.ToInt()) <= 1; 
}

...

bool check = noMoreThanOne(true, true, false, any, amount, of, bools);
于 2009-07-08T11:35:39.123 回答
9

你应该熟悉卡诺图。概念最常应用于电子产品,但在这里也非常有用。这很容易(认为维基百科的解释确实看起来很长——它很彻底)。

于 2009-07-08T11:41:25.307 回答
6

(A XOR B XOR C) OR NOT (A OR B OR C)

编辑:正如 Vilx 所指出的,这是不对的。

如果 A 和 B 都为 1,C 为 0,则 A XOR B 为 0,则整体结果为 0。

怎么样:NOT (A AND B) AND NOT (A AND C) AND NOT (B AND C)

于 2009-07-08T11:37:37.420 回答
3

如果你改变逻辑,如果你有任何一对布尔值都为真,你希望条件为假:

if (! ((a && b) || (a && c) || (b && c))) { ... }

对于完全不同的东西,您可以将布尔值放在一个数组中并计算有多少真实值:

if ((new bool[] { a, b, c }).Where(x => x).Count() <= 1) { ... }
于 2009-07-08T11:59:31.837 回答
3

我会追求最大的可维护性和可读性。

static bool ZeroOrOneAreTrue(params bool[] bools)
{
    return NumThatAreTrue(bools) <= 1;
}

static int NumThatAreTrue(params bool[] bools)
{
    return bools.Where(b => b).Count();
}
于 2009-07-08T12:07:05.957 回答
2

这里有很多答案,但我还有一个!

a ^ b ^ c ^ (a == b && b == c)
于 2012-02-02T20:25:43.710 回答
1

为给定真值表找到最小布尔表达式的一般方法是使用卡诺图:

http://babbage.cs.qc.edu/courses/Minimize/

网络上有几个在线最小化工具。这里的一个(链接到文章,虽然它是德语)找到以下表达式:

(!A && !B) || (!A && !C) || (!B && !C)

但是,如果您要提高代码的可读性,我可能会采用“sum<=1”的想法。请注意,并非所有语言都保证 false==0 和 true==1 ——但您可能已经意识到这一点,因为您已经在自己的解决方案中处理了它。

于 2009-07-08T11:48:34.073 回答
0

很好的逻辑:

+ = 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))

如果您愿意,请接受提示并进一步简化。

是的,让你自己熟悉卡诺图

于 2009-07-08T11:41:36.350 回答
0

取决于您是否想要易于理解您正在尝试做什么的东西,或者是逻辑上尽可能简单的东西。其他人正在发布逻辑上简单的答案,所以这里更清楚发生了什么(以及不同输入的结果):

  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"
于 2009-07-08T11:48:52.310 回答
0

我喜欢加法解决方案,但这里有一个 hack 也可以用位字段来做到这一点。

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 */ }
于 2009-07-08T12:10:35.763 回答
0

d的解决方案代码演示:

int total=0;
if (A) total++;
if (B) total++;
if (C) total++;

if (total<=1) // iff no more than one is true.
{
    // execute

}
于 2009-07-08T12:15:43.933 回答