下面的布尔表达式怎么写?

发布于 2024-07-26 15:38:22 字数 673 浏览 6 评论 0原文

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

 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 这是针对生产代码的,因此我更注重代码的可读性而不是性能。

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

I've got three boolean values A, B and C. I need to write an IF statement which will execute if and only if no more than one of these values is True. In other words, here is the truth table:

 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

What is the best way to write this? I know I can enumerate all possibilities, but that seems... too verbose. :P

Added: Just had one idea:

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

This checks that no two values are set. The suggestion about sums is OK as well. Even more readable maybe...

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

P.S. This is for production code, so I'm going more for code readability than performance.

Added 2: Already accepted answer, but for the curious ones - it's C#. :) The question is pretty much language-agnostic though.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

能否归途做我良人 2024-08-02 15:38:22

将它们视为整数 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);

how about treating them as integer 1's and 0's, and checking that their sum equals 1?

EDIT:

now that we know that it's c#.net, i think the most readable solution would look somewhat like

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

the above tucked away in a class library (appcode?) where we don't have to see it, yet can easily access it (ctrl+click in r#, for instance) and then the implementation will simply be:

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

...

bool check = noMoreThanOne(true, true, false, any, amount, of, bools);
晚风撩人 2024-08-02 15:38:22

您应该熟悉卡诺地图。 概念最常应用于电子产品,但在这里也非常有用。 这非常简单(虽然维基百科的解释看起来很长——但很彻底)。

You shold familiarize yourself with Karnaugh maps. Concept is most often applied to electronics but is very useful here too. It's very easy (thought Wikipedia explanation does look long -- it's thorough).

意中人 2024-08-02 15:38:22

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

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

如果A和B都为1,C为0,则A异或B为0,总结果为0。

怎么样:
非(A 和 B)且非(A 和 C)且非(B 和 C)

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

Edit: As pointed out by Vilx, this isn't right.

If A and B are both 1, and C is 0, A XOR B will be 0, the overall result will be 0.

How about:
NOT (A AND B) AND NOT (A AND C) AND NOT (B AND C)

记忆里有你的影子 2024-08-02 15:38:22

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

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

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

if ((new bool[] { a, b, c }).Where(x => x).Count() <= 1) { ... }

If you turn the logic around, you want the condition to be false if you have any pair of booleans that are both true:

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

For something completely different, you can put the booleans in an array and count how many true values there are:

if ((new bool[] { a, b, c }).Where(x => x).Count() <= 1) { ... }
情定在深秋 2024-08-02 15:38:22

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

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

static int NumThatAreTrue(params bool[] bools)
{
    return bools.Where(b => b).Count();
}

I'd go for maximum maintainability and readability.

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

static int NumThatAreTrue(params bool[] bools)
{
    return bools.Where(b => b).Count();
}
往日情怀 2024-08-02 15:38:22

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

a ^ b ^ c ^ (a == b && b == c)

There are many answers here, but I have another one!

a ^ b ^ c ^ (a == b && b == c)
め可乐爱微笑 2024-08-02 15:38:22

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

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

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

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

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

A general way of finding a minimal boolean expression for a given truth table is to use a Karnaugh map:

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

There are several online minimizers on the web. The one here (linked to from the article, it's in German, though) finds the following expression:

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

If you're going for code readability, though, I would probably go with the idea of "sum<=1". Take care that not all languages guarantee that false==0 and true==1 -- but you're probably aware of this since you've taken care of it in your own solution.

我喜欢麦丽素 2024-08-02 15:38:22

良好的逻辑:

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

如果需要,请接受提示并进一步简化。

是的,让您自己熟悉卡诺地图

Good ol' logic:

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

Take the hint and simplify further if you want.

And yeah, get your self familiar with Karnaugh Maps

万劫不复 2024-08-02 15:38:22

取决于你想要的是容易理解你想要做什么的东西,还是逻辑上尽可能简单的东西。 其他人发布了逻辑上简单的答案,因此这里是更清楚发生了什么(以及不同输入的结果)的答案:

  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"

Depends whether you want something where it's easy to understand what you're trying to do, or something that's as logically simple as can be. Other people are posting logically simple answers, so here's one where it's more clear what's going on (and what the outcome will be for different inputs):

  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"
半夏半凉 2024-08-02 15:38:22

我喜欢加法解决方案,但这里也有一个使用位字段来实现这一点的技巧。

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 */ }

I like the addition solution, but here's a hack to do that with bit fields as well.

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 */ }
乜一 2024-08-02 15:38:22

d的解决方案代码演示:

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

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

}

Code demonstration of d's solution:

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

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

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文