题
我有三个布尔值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)
此检查,没有两个值被设置。关于资金的建议是OK为好。甚至更可读也许...
(A?1:0)+(B 1:0)+(C?1:0)<= 1
P.S。这是生产代码,所以我要多为代码的可读性比性能。
新增2:已接受的答案,但对于好奇的 - 这是C#。 :)现在的问题是相当多的语言无关,但。
解决方案
怎么样将它们视为整数1和0的,并检查它们的和等于1?
修改强>:
现在,我们知道这是C#.NET,我觉得最可读的解决方案看起来有点像
public static class Extensions
{
public static int ToInt(this bool b)
{
return b ? 1 : 0;
}
}
以上在类库局促(?appcode),我们没有看到它,但可以很容易地访问它(CTRL +单击R·,例如),然后实施将仅仅是:
public bool noMoreThanOne(params bool[] bools)
{
return bools.ToList().Sum(b => b.ToInt()) <= 1;
}
...
bool check = noMoreThanOne(true, true, false, any, amount, of, bools);
其他提示
您shold熟悉卡诺图。概念最常应用于电子产品,但是是非常有用这里。这很容易(维基百科想解释看起来很长 - 这是彻底的)。
(A XOR B XOR C)OR NOT(A或B或C)
编辑:如Vilx指出的,这是不正确的
如果A和B都为1,C为0,A XOR B将是0,总的结果将是0
如何: NOT(A和B)和NOT(A和C)和NOT(B和C)
如果你把逻辑周围,你想要的条件是假的,如果你有任何一对布尔即都为真的:
if (! ((a && b) || (a && c) || (b && c))) { ... }
完全不同的东西,你可以把布尔在一个数组,计算有多少真实值有:
if ((new bool[] { a, b, c }).Where(x => x).Count() <= 1) { ... }
我会去维护最大和可读性。
static bool ZeroOrOneAreTrue(params bool[] bools)
{
return NumThatAreTrue(bools) <= 1;
}
static int NumThatAreTrue(params bool[] bools)
{
return bools.Where(b => b).Count();
}
有很多答案在这里,但我有一个又一个!
a ^ b ^ c ^ (a == b && b == c)
发现一个最小的布尔表达式为给定的真值表的一般方法是使用卡诺图:
http://babbage.cs.qc.edu/courses/Minimize/一>
有在网络上几个网上极小。这里的一个(从制品挂,它是在德国,尽管)发现下面的表达式:
(!甲&&!B)|| (!一个&&!C)|| (!乙&&!C)
如果你打算为代码的可读性,虽然,我可能会用“总和<= 1”的想法去。小心,并非所有的语言保证假== 0和真正的== 1 - 但你可能意识到了这一点,因为你已经采取了照顾它在自己的解决方案。
好醇”逻辑:
+ = 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))
采取提示,如果你想进一步简化。
和耶,让你自己熟悉卡诺图
要看你是否想要的东西在那里很容易理解你想要做什么,或者说这是因为可以在逻辑上简单。其他人张贴逻辑简单的答案,所以这里的一个地方更清楚发生了什么(什么结果将是不同的输入):
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"
我喜欢另外的解决方案,但这里有一个黑客这样做与位域为好。
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 */ }
D的溶液的代码示范:
int total=0;
if (A) total++;
if (B) total++;
if (C) total++;
if (total<=1) // iff no more than one is true.
{
// execute
}