检查至少三分之二的布尔值是否为真

Check if at least two out of three booleans are true

提问人: 提问时间:6/19/2010 最后编辑:7 revs, 6 users 49%user282886 更新时间:11/21/2023 访问量:199749

问:

一位面试官最近问了我这个问题:给定三个布尔变量 a、b 和 c,如果这三个变量中至少有两个为真,则返回 true。

我的解决方案如下:

boolean atLeastTwo(boolean a, boolean b, boolean c) {
    if ((a && b) || (b && c) || (a && c)) {
        return true;
    }
    else{
        return false;
    }
}

他说,这可以进一步改进,但如何改进呢?

java 布尔逻辑

评论

173赞 Finglas 6/19/2010
内联 return 语句。
82赞 Andrew Grimm 6/20/2010
atLeastTwo(iWantYou, iNeedYou, imEverGonnaLoveYou)
6赞 Ken 6/20/2010
Thorbjørn:C 不是用零/非零来表示布尔值吗?我认为这在 C 中甚至行不通,例如, .atLeastTwo(0,2,0)
93赞 BlueRaja - Danny Pflughoeft 6/23/2010
为什么人们会对最微不足道的问题投赞成票?
52赞 Jay 6/24/2010
一般且易于理解的问题会获得很多赞成票。非常具体和技术性的问题则不然。

答:

847赞 7 revs, 6 users 73%polygenelubricants #1

而不是写:

if (someExpression) {
    return true;
} else {
    return false;
}

写:

return someExpression;

至于表达本身,像这样:

boolean atLeastTwo(boolean a, boolean b, boolean c) {
    return a ? (b || c) : (b && c);
}

或者这个(以你觉得更容易掌握的为准):

boolean atLeastTwo(boolean a, boolean b, boolean c) {
    return a && (b || c) || (b && c);
}

它测试并且只测试一次,最多一次。abc

引用

评论

150赞 Juliet 6/20/2010
+1:这个谜题的好解决方案,但希望我们在现实世界中看不到这样的东西:)
125赞 Andrzej Doyle 6/20/2010
@Juliet:我不知道,我认为如果这是一个现实世界的要求(具有真实的变量名称),它会读得很好。想想看,这对我来说看起来不错。return hasGoodAttendance ? (passedCoursework || passed Exam) : (passedCoursework && passedExam)
18赞 Ken 6/20/2010
我不认为这看起来很糟糕,但如果将该领域的要求理解为“至少两个”,我认为它会更容易阅读。“至少 2 个布尔值是真的”这个想法足够通用,值得它自己的功能。atLeastTwo(hasgoodAttendance, passedCoursework, passedExam)
18赞 polygenelubricants 6/20/2010
@Lese:在面对面的面试中询问最微优化的代码是不切实际的,我敢说,没用。当由需求驱动时,微优化是由运行时分析结果指导的,而不是人类的本能(众所周知,这是可怕的)。你当然可以向受访者询问你进一步优化的过程;这比结果本身更重要。
18赞 Stephen P 6/22/2010
三元运算符是您应该能够阅读的常见成语。如果你读不懂它,你应该学习它,直到你能读懂为止。使用三元运算符并不是我认为贬义上的“聪明”的东西。但是,是的,如果您通常使用“至少两个”逻辑,我会将其作为方法调用的主体。
228赞 14 revs, 4 users 91%Rotsor #2

为什么不从字面上实现呢?:)

(a?1:0)+(b?1:0)+(c?1:0) >= 2

在C语言中,你可以直接写(或者为了非常安全)。a+b+c >= 2!!a+!!b+!!c >= 2

针对 TofuBeer 对 java 字节码的比较,这里做一个简单的性能测试:

class Main
{
    static boolean majorityDEAD(boolean a,boolean b,boolean c)
    {
        return a;
    }

    static boolean majority1(boolean a,boolean b,boolean c)
    {
        return a&&b || b&&c || a&&c;
    }

    static boolean majority2(boolean a,boolean b,boolean c)
    {
        return a ? b||c : b&&c;
    }

    static boolean majority3(boolean a,boolean b,boolean c)
    {
        return a&b | b&c | c&a;
    }

    static boolean majority4(boolean a,boolean b,boolean c)
    {
        return (a?1:0)+(b?1:0)+(c?1:0) >= 2;
    }

    static int loop1(boolean[] data, int i, int sz1, int sz2)
    {
        int sum = 0;
        for(int j=i;j<i+sz1;j++)
        {
            for(int k=j;k<j+sz2;k++)
            {
                sum += majority1(data[i], data[j], data[k])?1:0; 
                sum += majority1(data[i], data[k], data[j])?1:0; 
                sum += majority1(data[j], data[k], data[i])?1:0; 
                sum += majority1(data[j], data[i], data[k])?1:0; 
                sum += majority1(data[k], data[i], data[j])?1:0; 
                sum += majority1(data[k], data[j], data[i])?1:0; 
            }
        }
        return sum;
    }

    static int loop2(boolean[] data, int i, int sz1, int sz2)
    {
        int sum = 0;
        for(int j=i;j<i+sz1;j++)
        {
            for(int k=j;k<j+sz2;k++)
            {
                sum += majority2(data[i], data[j], data[k])?1:0; 
                sum += majority2(data[i], data[k], data[j])?1:0; 
                sum += majority2(data[j], data[k], data[i])?1:0; 
                sum += majority2(data[j], data[i], data[k])?1:0; 
                sum += majority2(data[k], data[i], data[j])?1:0; 
                sum += majority2(data[k], data[j], data[i])?1:0; 
            }
        }
        return sum;
    }

    static int loop3(boolean[] data, int i, int sz1, int sz2)
    {
        int sum = 0;
        for(int j=i;j<i+sz1;j++)
        {
            for(int k=j;k<j+sz2;k++)
            {
                sum += majority3(data[i], data[j], data[k])?1:0; 
                sum += majority3(data[i], data[k], data[j])?1:0; 
                sum += majority3(data[j], data[k], data[i])?1:0; 
                sum += majority3(data[j], data[i], data[k])?1:0; 
                sum += majority3(data[k], data[i], data[j])?1:0; 
                sum += majority3(data[k], data[j], data[i])?1:0; 
            }
        }
        return sum;
    }

    static int loop4(boolean[] data, int i, int sz1, int sz2)
    {
        int sum = 0;
        for(int j=i;j<i+sz1;j++)
        {
            for(int k=j;k<j+sz2;k++)
            {
                sum += majority4(data[i], data[j], data[k])?1:0; 
                sum += majority4(data[i], data[k], data[j])?1:0; 
                sum += majority4(data[j], data[k], data[i])?1:0; 
                sum += majority4(data[j], data[i], data[k])?1:0; 
                sum += majority4(data[k], data[i], data[j])?1:0; 
                sum += majority4(data[k], data[j], data[i])?1:0; 
            }
        }
        return sum;
    }

    static int loopDEAD(boolean[] data, int i, int sz1, int sz2)
    {
        int sum = 0;
        for(int j=i;j<i+sz1;j++)
        {
            for(int k=j;k<j+sz2;k++)
            {
                sum += majorityDEAD(data[i], data[j], data[k])?1:0; 
                sum += majorityDEAD(data[i], data[k], data[j])?1:0; 
                sum += majorityDEAD(data[j], data[k], data[i])?1:0; 
                sum += majorityDEAD(data[j], data[i], data[k])?1:0; 
                sum += majorityDEAD(data[k], data[i], data[j])?1:0; 
                sum += majorityDEAD(data[k], data[j], data[i])?1:0; 
            }
        }
        return sum;
    }

    static void work()
    {
        boolean [] data = new boolean [10000];
        java.util.Random r = new java.util.Random(0);
        for(int i=0;i<data.length;i++)
            data[i] = r.nextInt(2) > 0;
        long t0,t1,t2,t3,t4,tDEAD;
        int sz1 = 100;
        int sz2 = 100;
        int sum = 0;

        t0 = System.currentTimeMillis();

        for(int i=0;i<data.length-sz1-sz2;i++)
            sum += loop1(data, i, sz1, sz2);

        t1 = System.currentTimeMillis();

        for(int i=0;i<data.length-sz1-sz2;i++)
            sum += loop2(data, i, sz1, sz2);

        t2 = System.currentTimeMillis();

        for(int i=0;i<data.length-sz1-sz2;i++)
            sum += loop3(data, i, sz1, sz2);

        t3 = System.currentTimeMillis();

        for(int i=0;i<data.length-sz1-sz2;i++)
            sum += loop4(data, i, sz1, sz2);

        t4 = System.currentTimeMillis();

        for(int i=0;i<data.length-sz1-sz2;i++)
            sum += loopDEAD(data, i, sz1, sz2);

        tDEAD = System.currentTimeMillis();

        System.out.println("a&&b || b&&c || a&&c : " + (t1-t0) + " ms");
        System.out.println("   a ? b||c : b&&c   : " + (t2-t1) + " ms");
        System.out.println("   a&b | b&c | c&a   : " + (t3-t2) + " ms");
        System.out.println("   a + b + c >= 2    : " + (t4-t3) + " ms");
        System.out.println("       DEAD          : " + (tDEAD-t4) + " ms");
        System.out.println("sum: "+sum);
    }

    public static void main(String[] args) throws InterruptedException
    {
        while(true)
        {
            work();
            Thread.sleep(1000);
        }
    }
}

这在我的机器上打印以下内容(在 Intel Core 2 + sun java 1.6.0_15-b03 上运行 Ubuntu 和 HotSpot Server VM(14.1-b02,混合模式)):

第一次和第二次迭代:

a&&b || b&&c || a&&c : 1740 ms
   a ? b||c : b&&c   : 1690 ms
   a&b | b&c | c&a   : 835 ms
   a + b + c >= 2    : 348 ms
       DEAD          : 169 ms
sum: 1472612418

后续迭代:

a&&b || b&&c || a&&c : 1638 ms
   a ? b||c : b&&c   : 1612 ms
   a&b | b&c | c&a   : 779 ms
   a + b + c >= 2    : 905 ms
       DEAD          : 221 ms

我想知道,java VM会做些什么来降低(a + b + c >= 2)情况下的性能。

以下是如果我使用 VM 交换机运行 java 会发生什么:-client

a&&b || b&&c || a&&c : 4034 ms
   a ? b||c : b&&c   : 2215 ms
   a&b | b&c | c&a   : 1347 ms
   a + b + c >= 2    : 6589 ms
       DEAD          : 1016 ms

神秘。。。

如果我在 GNU Java Interpreter 中运行它,它会慢近 100 倍,但版本会获胜。a&&b || b&&c || a&&c

Tofubeer 使用运行 OS X 的最新代码的结果:

a&&b || b&&c || a&&c : 1358 ms
   a ? b||c : b&&c   : 1187 ms
   a&b | b&c | c&a   : 410 ms
   a + b + c >= 2    : 602 ms
       DEAD          : 161 ms

Paul Wagland 使用 Mac Java 的结果 1.6.0_26-b03-383-11A511

a&&b || b&&c || a&&c : 394 ms 
   a ? b||c : b&&c   : 435 ms
   a&b | b&c | c&a   : 420 ms
   a + b + c >= 2    : 640 ms
   a ^ b ? c : a     : 571 ms
   a != b ? c : a    : 487 ms
       DEAD          : 170 ms

评论

4赞 polygenelubricants 6/19/2010
a+b+c >= 2:这不适用于负面因素,对吧?你可能不得不做这件事,我不确定。!!a
8赞 Mark Peters 6/19/2010
<s>-1。你永远不应该对 C 这样做。你不知道 true 的值是什么(它可以很容易地是 -1).</s> 实际上,我猜 C99 在其标准中将 true 定义为 1。但我仍然不会这样做。
1赞 Rotsor 6/19/2010
如果您的输入是布尔运算的结果,这是否可能?C++中的“bool”类型可能吗?
2赞 Mark Peters 6/20/2010
@Rotsor:没有人说输入必须是布尔运算的结果。即使没有负数,你也是在玩火,就好像你把它定义为 2 一样,你的条件也会有假阳性。但我并不关心这一点,因为我不喜欢将布尔值混合到算术中的想法。您的 Java 解决方案很清楚,因为它不依赖于从布尔类型到整数类型的细微转换。
7赞 BalusC 6/20/2010
谨慎使用微基准测试:java.sun.com/docs/hotspot/HotSpotFAQ.html#benchmarking_simple
12赞 2 revs, 2 users 80%TofuBeer #3

最明显的一组改进是:

// There is no point in an else if you already returned.
boolean atLeastTwo(boolean a, boolean b, boolean c) {
    if ((a && b) || (b && c) || (a && c)) {
        return true;
    }
    return false;
}

然后

// There is no point in an if(true) return true otherwise return false.
boolean atLeastTwo(boolean a, boolean b, boolean c) {
    return ((a && b) || (b && c) || (a && c));
}

但这些改进是微不足道的。

34赞 moonshadow #4

您不需要使用运算符的短路形式。

return (a & b) | (b & c) | (c & a);

这执行的逻辑操作数量与您的版本相同,但完全无分支。

评论

11赞 Mark Peters 6/19/2010
当 1 个可以做到时,为什么要强制执行 5 个评估?实际上,它确实不会执行相同数量的逻辑运算。事实上,它总是会表现得更好。
2赞 Peter Tillemans 6/20/2010
我认为混合二进制算术和布尔算术是一个坏主意。这就像用扳手在墙上拧螺丝一样。最糟糕的是它们有不同的语义。
12赞 Stephen C 6/20/2010
@Mark - 它可能会更快......取决于不正确的分支预测对 CPU 管道的影响。但是,最好将此类微优化留给 JIT 编译器。
4赞 TofuBeer 6/20/2010
在 Java(或任何其他语言)中做这样的事情是可以的......有几个警告:1)它需要更快(在这种情况下,我相信是,请参阅我的第二个答案)2)最好更快(不确定是否是),3)最重要的是记录在案,因为它是“奇怪的”。只要它有目的并且有记录,就可以在有意义的时候“打破规则”。
11赞 starblue 6/20/2010
@Peter Tillemans 没有与二进制运算符混合,在 Java 中这些是布尔运算符。
145赞 2 revs, 2 users 67%danatel #5

可读性应该是目标。阅读代码的人必须立即理解您的意图。所以这是我的解决方案。

int howManyBooleansAreTrue =
      (a ? 1 : 0)
    + (b ? 1 : 0)
    + (c ? 1 : 0);

return howManyBooleansAreTrue >= 2;

评论

22赞 Adrian Grigore 6/20/2010
我同意这个前提,但是(a & b) ||(b & c) ||恕我直言,(a & & c)比您的解决方案更具可读性。
65赞 Arafangion 6/20/2010
嗯,现在我需要一个“四分之二的布尔值”版本......Danatel 的版本现在容易多了。
7赞 retronym 6/23/2010
或者在 Scala 中:Seq(true, true, false).map(if (_) 1 else 0).sum >= 2
5赞 Seun Osewa 7/25/2010
@retronym:嗯,没有。Java 方式在 Scala 中运行良好,可读性更强,效率更高。
146赞 Jack #6

这类问题可以用卡诺地图来解决:

      | C | !C
------|---|----
 A  B | 1 | 1 
 A !B | 1 | 0
!A !B | 0 | 0
!A  B | 1 | 0

从中可以推断出第一行需要一组,第一列需要两组,从而获得多元润滑剂的最优解:

(C && (A || B)) || (A && B)  <---- first row
       ^
       |
   first column without third case

评论

11赞 Tachy 6/22/2010
@Justin,Karnaugh 映射将逻辑运算的数量从 3 个 ND 和 2 个 OR 减少到 2 个 ND 和 2 个 OR。@Jack,谢谢你提醒我卡诺地图的存在。
15赞 Justin R. 6/22/2010
+1 表示新事物。我的下一个功能规范将包括一个 K-map,无论它是否需要它。
2赞 moala 2/2/2012
也许可读性差可以通过 (1) 注释中的适当表格和 (2) 适当的单元测试来弥补......+1 用于在学校学到的有用的东西。
13赞 2 revsTofuBeer #7

在这里获取答案(到目前为止):

public class X
{
    static boolean a(final boolean a, final boolean b, final boolean c)
    {
    return ((a && b) || (b && c) || (a && c));
    }

    static boolean b(final boolean a, final boolean b, final boolean c)
    {
    return a ? (b || c) : (b && c);
    }

    static boolean c(final boolean a, final boolean b, final boolean c)
    {
    return ((a & b) | (b & c) | (c & a));
    }

    static boolean d(final boolean a, final boolean b, final boolean c)
    {
    return ((a?1:0)+(b?1:0)+(c?1:0) >= 2);
    }
}

并通过反编译器运行它们(javap -c X >结果.txt):

Compiled from "X.java"
public class X extends java.lang.Object{
public X();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

static boolean a(boolean, boolean, boolean);
  Code:
   0:   iload_0
   1:   ifeq    8
   4:   iload_1
   5:   ifne    24
   8:   iload_1
   9:   ifeq    16
   12:  iload_2
   13:  ifne    24
   16:  iload_0
   17:  ifeq    28
   20:  iload_2
   21:  ifeq    28
   24:  iconst_1
   25:  goto    29
   28:  iconst_0
   29:  ireturn

static boolean b(boolean, boolean, boolean);
  Code:
   0:   iload_0
   1:   ifeq    20
   4:   iload_1
   5:   ifne    12
   8:   iload_2
   9:   ifeq    16
   12:  iconst_1
   13:  goto    33
   16:  iconst_0
   17:  goto    33
   20:  iload_1
   21:  ifeq    32
   24:  iload_2
   25:  ifeq    32
   28:  iconst_1
   29:  goto    33
   32:  iconst_0
   33:  ireturn

static boolean c(boolean, boolean, boolean);
  Code:
   0:   iload_0
   1:   iload_1
   2:   iand
   3:   iload_1
   4:   iload_2
   5:   iand
   6:   ior
   7:   iload_2
   8:   iload_0
   9:   iand
   10:  ior
   11:  ireturn

static boolean d(boolean, boolean, boolean);
  Code:
   0:   iload_0
   1:   ifeq    8
   4:   iconst_1
   5:   goto    9
   8:   iconst_0
   9:   iload_1
   10:  ifeq    17
   13:  iconst_1
   14:  goto    18
   17:  iconst_0
   18:  iadd
   19:  iload_2
   20:  ifeq    27
   23:  iconst_1
   24:  goto    28
   27:  iconst_0
   28:  iadd
   29:  iconst_2
   30:  if_icmplt   37
   33:  iconst_1
   34:  goto    38
   37:  iconst_0
   38:  ireturn
}

你可以看到?:比你原来的修复版本稍微好一些。最好的是完全避免分支的那个。从指令较少(在大多数情况下)的角度来看,这是件好事,并且对于 CPU 的分支预测部分更好,因为分支预测中的错误猜测会导致 CPU 停滞。

我想说最有效的是 moonshadow 整体上的那个。它平均使用最少的指令,并减少了 CPU 中管道停顿的机会。

为了 100% 确定,您需要找出每条指令的成本(以 CPU 周期为单位),不幸的是,这并不容易获得(您必须查看热点的来源,然后查看 CPU 供应商的规格,了解每个生成的指令所花费的时间)。

请参阅 Rotsor 更新的答案,了解代码的运行时分析。

评论

5赞 David Conrad 5/30/2012
你只看字节码。据您所知,JIT 将采用字节码中带有分支的版本,并将其转换为本机代码中没有分支的版本。但人们倾向于认为字节码中的分支越少越好。
15赞 malu #8
boolean atLeastTwo(boolean a, boolean b, boolean c) 
{
  return ((a && b) || (b && c) || (a && c));
}
13赞 2 revsDavid R Tribble #9

直接代码的另一个示例:

int  n = 0;
if (a) n++;
if (b) n++;
if (c) n++;
return (n >= 2);

显然,这不是最简洁的代码。

补遗

另一个(略微优化的)版本:

int  n = -2;
if (a) n++;
if (b) n++;
if (c) n++;
return (n >= 0);

假设与 0 的比较将比与 2 的比较使用更快(或更少)的代码,这可能会运行得稍微快一些。

评论

0赞 Ash 7/19/2010
+1 @Loadmaster,对不起,你错了!这是这里最简洁的答案。(即简短而清晰地表达);)
0赞 M. Mimpen 1/20/2014
微优化:比因为在执行增量之前必须创建另一个副本而要快。++nn++
0赞 David R Tribble 1/23/2014
@M.Mimpen:仅适用于类对象。对于原始类型(如上所述),任何像样的编译器都会将每个操作编译为单个 CPU 指令,无论是前指令还是后指令。n++
30赞 Carl Manaster #10

下面是一个测试驱动的通用方法。不像迄今为止提供的大多数解决方案那样“高效”,但清晰、经过测试、有效且通用。

public class CountBooleansTest extends TestCase {
    public void testThreeFalse() throws Exception {
        assertFalse(atLeastTwoOutOfThree(false, false, false));
    }

    public void testThreeTrue() throws Exception {
        assertTrue(atLeastTwoOutOfThree(true, true, true));
    }

    public void testOnes() throws Exception {
        assertFalse(atLeastTwoOutOfThree(true, false, false));
        assertFalse(atLeastTwoOutOfThree(false, true, false));
        assertFalse(atLeastTwoOutOfThree(false, false, true));
    }

    public void testTwos() throws Exception {
        assertTrue(atLeastTwoOutOfThree(false, true, true));
        assertTrue(atLeastTwoOutOfThree(true, false, true));
        assertTrue(atLeastTwoOutOfThree(true, true, false));
    }

    private static boolean atLeastTwoOutOfThree(boolean b, boolean c, boolean d) {
        return countBooleans(b, c, d) >= 2;
    }

    private static int countBooleans(boolean... bs) {
        int count = 0;
        for (boolean b : bs)
            if (b)
                count++;
        return count;
    }
}

评论

9赞 Rotsor 6/20/2010
哇,在看到这个之前,我从未见过经过全面测试的方法。
52赞 CaptainCasey 6/21/2010
我个人觉得这段代码很糟糕,原因有很多。我不会投反对票,但如果我在生产代码中看到这一点,我会诅咒。一个非常简单的布尔运算不需要像这样复杂。
11赞 Carl Manaster 6/21/2010
我很想知道你的理由,@CaptainCasey。我认为这是非常好的代码。有一个很好的广义函数,易于理解,易于验证,还有一个利用它的特定函数,也易于理解和验证。在现实世界中,我会把它们公之于众,并把它们放在另一个班级中;除此之外 - 我很乐意将此代码投入生产。哦 - 是的 - 我会将 countBooleans() 重命名为 countTrue()。
5赞 atamanroman 6/22/2010
如果不是关于性能,这个解决方案对我来说几乎是完美的:非常易于阅读和可扩展。这正是 var-args 的用途。
9赞 Christoffer Hammarström 12/20/2010
什么鬼,人们?这是清晰且经过充分测试的代码,它看起来很多的唯一原因是因为它包含测试。A+++,会再次投赞成票。
14赞 4 revsAnurag #11

这是另一个使用 map/reduce 的实现。这在分布式环境中可以很好地扩展到数十亿布尔©值。使用 MongoDB:

创建布尔值数据库:values

db.values.insert({value: true});
db.values.insert({value: false});
db.values.insert({value: true});

创建地图,reduce功能:

编辑:我喜欢 CurtainDog 关于将 map/reduce 应用于通用列表的回答,所以这里有一个 map 函数,它接受一个回调来确定是否应该计算一个值。

var mapper = function(shouldInclude) {
    return function() {
        emit(null, shouldInclude(this) ? 1 : 0);
    };
}

var reducer = function(key, values) {
    var sum = 0;
    for(var i = 0; i < values.length; i++) {
        sum += values[i];
    }
    return sum;
}

运行 map/reduce:

var result = db.values.mapReduce(mapper(isTrue), reducer).result;

containsMinimum(2, result); // true
containsMinimum(1, result); // false


function isTrue(object) {
    return object.value == true;
}

function containsMinimum(count, resultDoc) {
    var record = db[resultDoc].find().next();
    return record.value >= count;
}

评论

0赞 SyntaxT3rr0r 9/8/2011
@Anurag:尽管我非常喜欢 M/R 和 Google 最近给予它的曝光率(即使它不是 FP 中真正的 M/R),但我倾向于对你的答案说废话。有数十亿行代码在执行现实世界 [TM] 的“东西”,其中没有使用一行映射/缩减。有人用这个问题来回答这样的问题,在我的书中肯定被标记为:“试图扮演聪明人”。更不用说大多数面试官都无法判断你是否在胡说八道,因为他们实际上从未在他们的职业生涯中使用 M/R 编写过一个程序。
2赞 Anurag 9/9/2011
@Syntax - 每个人都有权发表自己的意见。我的答案只是另一种看待问题的方法。当然,对于 3 个布尔值来说,这听起来有些夸张,但这并不意味着我试图成为这里的聪明人。这是每个人都使用的一种常见的解决问题的方法 - 将问题分解成小块。这就是数学归纳法的工作原理,这就是大多数递归算法的工作原理,这就是人们解决问题的一般方式。
12赞 barrowc #12

还有另一种方法可以做到这一点,但不是很好的方法:

return (Boolean.valueOf(a).hashCode() + Boolean.valueOf(b).hashCode() + Boolean.valueOf(c).hashCode()) < 3705);

哈希码值固定为 1231 表示 true,1237 表示 false,因此同样可以使用Boolean<= 3699

评论

1赞 Peter Lawrey 6/20/2010
或 (a?1:0)+(b?1:0)+(c?1:0) >= 2
4赞 2 revs, 2 users 67%abelito #13

最简单的方法(IMO)不会混淆且易于阅读:

// Three booleans, check if two or more are true

return ( a && ( b || c ) ) || ( b && c );

评论

0赞 abelito 6/22/2010
在功能上,它是一样的。从语法上讲,对于那些不习惯使用问号条件运算符的人来说,它更容易阅读。我敢打赌,知道如何使用 AND 和 OR 运算符的人比知道如何使用问号条件运算符的人多。原来的问题要求一个“改进的答案”。公认的答案确实简化了答案,但提出了一个非常有趣的问题,即人们认为改进是什么。您编程是为了通用可读性还是为了简单性?对我来说,这是对公认的答案的改进:)
0赞 nico 6/22/2010
个人喜好。对我来说,比这个解决方案更容易理解更清洁的三元运算符。
1赞 Vivian River 6/23/2010
啊,是的,我看到了这个问题,想知道为什么没有其他人提到这个解决方案。如果你把OP的逻辑写成布尔代数,你会得到AB+A C+BC,它有五个运算。通过关联属性,可以写出 A*(B+C)+BC,它有四个运算。
0赞 user85421 6/25/2010
这和杰克的回答(6 月 19 日)一样,只是更改了*变量“名称......(C && (A || B)) || (A && B)
2赞 4 revs, 4 users 75%labratmatt #14

三元运算符让书的汁液流动起来,但它们可能会令人困惑(使代码的可维护性降低,从而增加了错误注入的可能性)。杰夫·阿特伍德(Jeff Attwood)在这里说得很好:

这是权衡的一个完美例子 一次完全没有意义的 节省了数十个写入时间 阅读时间理解惩罚 -- 它 让我思考。

为了避免使用三元运算符,我创建了以下函数:

function atLeastTwoTrue($a, $b, $c) {
    $count = 0;

    if ($a) { $count++; }
    if ($b) { $count++; }
    if ($c) { $count++; }

    return $count >= 2;
}

这是否与其他一些解决方案一样酷?不。更容易理解吗?是的。这会导致更易于维护、更少的错误代码吗?是的。

评论

2赞 ChrisF 6/22/2010
为什么不简单地?这也是这个答案的重复 - stackoverflow.com/questions/3076078/......return ($count >= 2);
0赞 labratmatt 6/22/2010
@ChrisF if () {return bool} 对我来说更清楚。我可以看到有些人认为它太冗长了。我的解决方案与 stackoverflow.com/questions/3076078/ 非常相似,但它更完整,并且包含一些理由(关于三元运算符的文本令人困惑)。
5赞 Jeremy Friesner 6/22/2010
就我个人而言,我发现多个 if 语句比三元运算符更让我思考,因为每个 if 语句都代表不同的可能执行路径。单行 OTOH 将始终将值设置在等号左侧一次,无论在等号右侧使用多少个三元运算符。
4赞 Luciano 6/22/2010
我更喜欢三元运算符,而不是我替换的多行运算符。我经常(在遗留代码中)将 ~10 行减少到一行三元。更少的文本 = 屏幕上的更多代码 = 更多的上下文。
2赞 mpen 6/22/2010
好好先生。。。这不仅仅是为了酷。三元较。少读,少理解。除非你真的和他们作斗争,否则一个小三元比......您在那里有 8 条线路和分支机会。
5赞 2 revs, 2 users 59%Duby #15
Function ReturnTrueIfTwoIsTrue(bool val1, val2, val3))
{
     return (System.Convert.ToInt16(val1) +
             System.Convert.ToInt16(val2) +
             System.Convert.ToInt16(val3)) > 1;
}

执行此操作的方法太多了......

评论

3赞 BalusC 6/22/2010
看起来更像 C#。这应该在答案中提到,因为问题是针对 Java 的:)
9赞 4 revs, 3 users 79%Roman A. Taycher #16

我不喜欢三元(从顶部答案开始),而且我认为我没有看到有人提到它。它是这样写的:return a ? (b || c) : (b && c);

boolean atLeastTwo(boolean a, boolean b, boolean c) {
    if (a) {
        return b||c;
    } 
    else {
        return b&&C;
    }
510赞 Tim Stone #17

只是为了用XOR来回答一个相对直接的问题......

return a ^ b ? c : a

评论

166赞 Rotsor 6/22/2010
哇,很酷的解决方案。但对我来说,它的倒置版本更容易理解:a==b ?答:C
5赞 alexanderpas 6/23/2010
一个 ^ b ?c : a ^ b ?c : a ^ b ?c : a
4赞 EightyOne Unite 7/16/2010
耶。。XOR受到如此糟糕的报道,你很少有机会使用它。
19赞 Tikhon Jelvis 9/10/2010
@Stimul8d也许是因为,对于布尔值,它与 != 相同,但可读性较差?弄清楚这对我来说是一个尤里卡时刻......
2赞 flanglet 4/2/2012
我更喜欢纯二进制形式:return ((a^b) & c) |(a&b)。它是无分支的(更快)且易于阅读:(a 或 b 为真,c 为真)或(a 和 b 均为真)。请注意,(a|b) 和 (a^b) 都使用此公式。
0赞 itpatil #18
function atLeastTwoTrue($a, $b, $c) {

  int count = 0;
  count = (a ? count + 1 : count);
  count = (b ? count + 1 : count);
  count = (c ? count + 1 : count);
  return (count >= 2);
}

评论

2赞 mpen 6/22/2010
呵呵......为什么?!已经发布的其他计数方法要好得多!
5赞 2 revs, 2 users 73%Mark Edgar #19

C 解决方案。

int two(int a, int b, int c) {
  return !a + !b + !c < 2;
}

或者您可能更喜欢:

int two(int a, int b, int c) {
  return !!a + !!b + !!c >= 2;
}
4赞 2 revsKevin #20
return 1 << $a << $b << $c >= 1 << 2;

评论

0赞 Kevin 6/22/2010
在提出这个问题之前没有看到 Suvega 的答案,几乎是一样的。
0赞 Mark Edgar 6/22/2010
这真的有效吗?我假设这是 PHP,但我无法访问它,但我只想问你:如果 $a 为 0 会发生什么?
0赞 Kevin 6/22/2010
@Mark 如果 $a 为 0,它实际上不起作用。这是一个疏忽。感谢您指出这一点。:)
24赞 memet #21

总结一下。它被称为布尔代数是有原因的:

  0 x 0 = 0
  1 x 0 = 0
  1 x 1 = 1

  0 + 0 = 0
  1 + 0 = 1
  1 + 1 = 0 (+ carry)

如果你看一下那里的真值表,你可以看到乘法是布尔值,而简单的加法是异或。

要回答您的问题,请执行以下操作:

return (a + b + c) >= 2

评论

2赞 Torbjørn Kristoffersen 6/22/2010
在我看来,这是最优雅的解决方案。
10赞 tomdemuyt 6/22/2010
不过,新手错误,布尔值不是 0,这并不意味着它总是 1。
14赞 Jay 6/24/2010
除了帖子上的标签上写着“Java”,当它们在 Java 中被定义为布尔值时,你不能写“a+b+c”。
0赞 David R Tribble 11/16/2013
要在 Java 中工作,它必须是 .return ((a?1:0) + (b?1:0) + (c?1:0)) >= 2
0赞 Carlo Wood 1/1/2018
呃,我投了这个票,因为我认为这是一个 C++ 问题......我为什么要阅读 java 问题?:/
-7赞 Brandon #22

我的第一个想法是

return (a||b)&&(b||c)

但为了便于阅读,我喜欢你们建议的更好的 a+b+c>=2 解决方案

评论

7赞 Timothy Fries 6/22/2010
当 a 和 c 为 false,而只有 b 为 true 时,您的答案将返回不正确的值。
2赞 Kintar #23

这绝对是一个关于你如何解决问题/思考的问题,而不是你的实际编码能力。

稍微简洁的版本可能是

返回 ((a ^ b) && (b ^ c)) ^ b

但就像之前的海报所说的那样,如果我在我正在处理的任何代码中看到这一点,就会有人听到。:)

5赞 2 revs, 2 users 89%blakecallens #24

字面解释适用于所有主要语言:

return (a ? 1:0) + (b ? 1:0) + (c ? 1:0) >= 2;

但我可能会让人们更容易阅读,并扩展到三个以上——这似乎被许多程序员遗忘了:

boolean testBooleans(Array bools)
{
     int minTrue = ceil(bools.length * .5);
     int trueCount = 0;

     for(int i = 0; i < bools.length; i++)
     {
          if(bools[i])
          {
               trueCount++;
          }
     }
     return trueCount >= minTrue;
}
7赞 Joe Enos #25

我想我还没有看到这个解决方案:

boolean atLeast(int howMany, boolean[] boolValues) {
  // check params for valid values

  int counter = 0;
  for (boolean b : boolValues) {
    if (b) {
      counter++;

      if (counter == howMany) {
        return true;
      }
    }
  }
  return false;
}

它的优点是,一旦它达到您正在寻找的数字,它就会中断。因此,如果这是“这 1,000,000 个值中至少有 2 个是真的”,而前两个值实际上是真的,那么它应该比一些更“正常”的解决方案更快。

评论

0赞 Joe Enos 6/22/2010
那可能应该是:if (++counter == howMany) 而不是递增然后单独检查。
2赞 Joe Enos 6/22/2010
甚至更短:if (b & (++counter == howMany))
1赞 Stephen 6/22/2010
我会这样做,这样更容易调用,但仍然需要一个数组boolean ... boolValues
0赞 Joe Enos 6/22/2010
我不了解我的 Java - 不知道它的存在。有点奇怪的语法,但它很有用 - 每隔一段时间我就会在 C#(params 关键字)中这样做,它确实使调用起来更好。或者,我不了解 Java,但在 .NET 中,数组和所有集合都实现了 IEnumerable<T>,所以我可能会使用 Java 的任何等价物。
0赞 Iain Sproat 6/24/2010
与 2of3 示例相比,其性能如何?返回一个?(b || c) : (b & c);
8赞 3 revs, 2 users 88%Vagif Verdi #26

Clojure 中:

(defn at-least [n & bools]
  (>= (count (filter true? bools)) n)

用法:

(at-least 2 true false true)

评论

2赞 dsmith 6/22/2010
+1 伟大的通用版本显示了 Lisps 的强大功能。谢谢
1赞 dai #27

X = 或(a+b,c)

a b c X

1 1 0 1

0 0 1 1

0 1 1 1

评论

0赞 Don Hatch 11/23/2021
这是什么语言?OR 是什么意思?(布尔值?+ 是什么意思?(这个问题被标记为 java,其中 + 不是您可以在布尔值上执行的操作,并且该语言中没有任何“OR”。
2赞 supercat #28

如果目标是为三个操作数返回按位三分之二的值,则算术和迭代方法往往相对无效。在许多 CPU 架构上,一个好的形式是“return ((a |b) & c) |(a&b);”。这需要四个布尔运算。在单累加器机器(常见于小型嵌入式系统)上,每字节总共需要 7 条指令。表格“return (a & b) |(a&c) |(b&c);”也许看起来更好,但它需要五个布尔运算,或者在单个累加器机器上每字节九个指令。

顺便说一句,在CMOS逻辑中,计算“不是三分之二”需要12个晶体管(相比之下,一个逆变器需要两个,一个双输入NAND或NOR需要4个,一个3输入NAND或NOR需要6个)。

-4赞 gnrfan #29

我相信使用普通的布尔运算符 (a || b) && (b || c) 很好,而且更简单。

您可以将 3 个字母中的任何一个与其他两个字母中的任何一个交换,并且它仍然是相同的表达。

评论

0赞 Kevin 6/22/2010
除了这个答案是错误的。如果只有 b 为 true,它将返回 true
0赞 gnrfan 6/26/2010
你是对的。所以我坚持 a+b+c>=2。也适用于 PHP 和 Python。
2赞 Kate Gregory #30

我没有看到其他人指出的一件事是,在求职面试的“请给我写一些代码”部分的标准做法是,当你说你完成了时,说“你能改进吗?”或者“你对此完全满意吗”或“这是否尽可能优化?您可能会听到“您将如何改进”,因为“这可能会得到改进;如何?在这种情况下,将成语更改为 just 是一种改进 - 但请注意,有时他们只是想看看您对问题的反应。我听说有些面试官会坚持认为完美的代码存在缺陷,只是为了看看你如何应对它。if(x) return true; else return false;return x

3赞 2 revs, 2 users 74%Matt Billenstein #31

这种读起来更好:

if (a) {
    return b || c;
} 
else {
    return b && c;
}
2赞 ZaBlanc #32

这个问题的最佳答案应该是“作为一名员工,重要的是我写它,这样我的意思才能清晰,同时在必要时保持效率。我是这样写的:

function atLeastTwoAreTrue(a, b, c) {
    return (a && b) || (b && c) || (a && c);
}

实际上,这个测试是如此人为,以至于如果你用一个简单的注释来适应它,那么编写一个最快、最神秘的方法是完全可以接受的。但是,总的来说,在这个单行世界中,我们需要在这个世界上具有更多可读性的代码。:-)

4赞 3 revs, 3 users 44%z-index #33

通过真值表计算:

return (a & b) | (c & (a ^ b));

评论

4赞 z-index 6/22/2010
好吧,原来的解决方案更容易。
162赞 3 revs, 2 users 62%Boann #34
return (a==b) ? a : c;

解释:

如果 ,则两者都为真或两者都为假。如果两者都为真,则我们已找到两个真布尔值,并且可以返回 true(通过返回 )。如果两者都为 false,则即使为 true,也不能有两个 true 布尔值,因此我们返回 false(通过返回 )。这就是部分。怎么样?好吧,如果为假,那么恰好有一个或必须为真,所以我们找到了第一个真布尔值,唯一重要的是如果也是真的,所以我们返回作为答案。a==baca(a==b) ? a: ca==babcc

评论

11赞 CurtainDog 6/23/2010
C 甚至从未被测试过......明!
0赞 Christophe Roussy 5/21/2013
使用相等的传递关系和布尔值为真或假的事实 +1
3赞 Adrian 8/16/2013
太优雅了!我不得不用笔和纸检查才能相信它:) 向你致敬,先生!
11赞 Ben Millwood 12/25/2016
我认为这是“如果并同意,他们拥有多数票,所以随便什么,否则,他们不同意,决定性的一票也是如此”abc
3赞 Ben Manes #35

仅供参考,这只是一个完整加法器的执行位。在硬件中,您可以使用逻辑工作量根据不同的布尔表达式确定最佳电路。我猜想,传统的异或解决方案会比海报所呈现的不那么简洁的表达需要更多的努力。

2赞 3 revs, 2 users 72%Aaron #36

C# 中,从我的头顶上:

public bool lol(int minTrue, params bool[] bools)
{
    return bools.Count( ( b ) => b ) >= minTrue;
}

应该很快。

呼叫如下所示:

lol( 2, true, true, false );

这样,您将规则(两个必须为 true)留给调用者,而不是将它们嵌入到方法中。

4赞 3 revs, 2 users 78%Rex Barzee #37

作为 @TofuBeer TofuBeer 优秀帖子的补充,请考虑 @pdox pdox 的回答:

static boolean five(final boolean a, final boolean b, final boolean c)
{
    return a == b ? a : c;
}

还要考虑它的反汇编版本,如“javap -c”所示:

static boolean five(boolean, boolean, boolean);
  Code:
    0:    iload_0
    1:    iload_1
    2:    if_icmpne    9
    5:    iload_0
    6:    goto    10
    9:    iload_2
   10:    ireturn

PDOX 的答案编译为比之前任何答案都少的字节码。它的执行时间与其他时间相比如何?

one                5242 ms
two                6318 ms
three (moonshadow) 3806 ms
four               7192 ms
five  (pdox)       3650 ms

至少在我的电脑上,pdox 的答案只比 @moonshadow moonshadow 的答案略快,使 pdox 成为整体上最快的(在我的 HP/Intel 笔记本电脑上)。

15赞 kerkeslager #38

这真的取决于你所说的“改进”是什么意思:

清晰?

boolean twoOrMoreAreTrue(boolean a, boolean b, boolean c)
{
    return (a && b) || (a && c) || (b && c);
}

瑟瑟?

boolean moreThanTwo(boolean a, boolean b, boolean c)
{
    return a == b ? a : c;
}

更笼统?

boolean moreThanXTrue(int x, boolean[] bs)
{
    int count = 0;

    for(boolean b : bs)
    {
        count += b ? 1 : 0;

        if(count > x) return true;
    }

    return false;
}

更具可扩展性?

boolean moreThanXTrue(int x, boolean[] bs)
{
    int count = 0;

    for(int i < 0; i < bs.length; i++)
    {
        count += bs[i] ? 1 : 0;

        if(count > x) return true;

        int needed = x - count;
        int remaining = bs.length - i;

        if(needed >= remaining) return false;
    }

    return false;
}

更快?

// Only profiling can answer this.

哪一个是“改进”,很大程度上取决于情况。

2赞 3 revs, 3 users 56%endy #39
int count = 0;

boolean atLeastTwo(boolean a, boolean b, boolean c) {
    if (a)
        count++;
    if (b)
        count++;
    if (c)
        count++;

    return count > 1;
}
3赞 user373826 #40

在 Ruby 中:

[a, b, c].count { |x| x } >= 2

它可以在 JavaVM 上的 JRuby 中运行。;-)

2赞 CurtainDog #41

所提问题中的 2 和 3 绝对是神奇的数字。“正确”的答案将取决于面试官是否试图掌握布尔逻辑(我认为 pdox 的答案在这方面无法胜过)或你对架构问题的理解。

我倾向于使用map-reduce解决方案,该解决方案将接受具有任意条件的任何类型的列表。

2赞 2 revsthis. __curious_geek #42

我找到了这个解决方案。

boolean atLeastTwo(boolean a, boolean b, boolean c) {
    bool result = !(a ^ b ^ c) && !(!a & !b & !c) || (a & b & c);
    return result;
}
3赞 2 revs, 2 users 84%Jay #43

当我看到这个问题时,我的第一个想法是:

int count=0;
if (a)
    ++count;
if (b)
    ++count;
if (c)
    ++count;
return count>=2;

在看到其他帖子后,我承认

return (a?1:0)+(b?1:0)+(c?1:0)>=2;

要优雅得多。我想知道相对运行时是什么。

不过,无论如何,我认为这种解决方案比

return a&b | b&c | a&c;

多样性,因为 is 更容易扩展。如果稍后我们添加必须测试的第四个变量怎么办?如果变量的数量是在运行时确定的,并且我们被传递了一个未知大小的布尔数组,该怎么办?依赖于计数的解决方案比依赖于列出每个可能的组合的解决方案更容易扩展。此外,在列出所有可能的组合时,我怀疑更容易犯错误。就像尝试为“任意 3 个中的 4 个”编写代码一样,并确保您既不会遗漏任何代码,也不会重复任何代码。现在尝试使用“任意 5 个中的 7”。

评论

0赞 Joan Rieu 6/29/2010
你可以更进一步:我相信在 C 中你可以返回 a+b+c>1;
0赞 Jay 7/7/2010
Fififox:没错,但问题被标记为“Java”,这是行不通的。(a?1:0) 解决方案是最接近于您建议的 C 解决方案的 Java 解决方案。我敢肯定,人们可以无休止地争论相对的优点。在 C 中,您可以通过将布尔值处理为整数来执行简单的快捷方式;在 Java 中,您可以不小心将布尔值视为 int 来保护自己免受伤害。
3赞 2 revsstinky472 #44

他可能不是在寻找任何复杂的东西,比如按位比较运算符(通常不是错综复杂的,但有布尔值,使用按位运算符非常奇怪)或非常迂回的东西,比如转换为 int 并将它们相加。

解决这个问题最直接、最自然的方法是用这样的表达方式:

a ? (b || c): (b && c)

如果您愿意,可以将其放在函数中,但它不是很复杂。该解决方案在逻辑上简洁而高效。

2赞 2 revs, 2 users 71%Egalitarian #45

设三个布尔值分别为 A、B 和 C。

您可以使用 k-MAP 并附带布尔表达式。

在本例中,布尔表达式将是A(B+C) + C

return (A && (B || C )) || C;

评论

0赞 9/6/2010
这难道不是只返回 C 为真吗?
0赞 Egalitarian 9/7/2010
哎呀。。。我忘了添加一些东西......其 if((A & (B ||C )) ||(B&C){ 返回 true;否则返回 false;
1赞 Matt Joiner #46

C:

if (!!a + !!b + !!c >= 2)
3赞 2 revs, 2 users 78%Dimitre Novatchev #47

它应该是:

(a || b && c) && (b || c && a)

此外,if 会自动转换为 和 :true1false0

(a + b*c) * (b + c*a) > 0
0赞 2 revs, 2 users 69%Derek Organ #48

在我看来,三分之二是相当任意的数字,该函数应该与任意数字一起使用。因此,为了回答这个问题,我会编写一个函数来计算数组中的 x 是否为真,例如,

bool istrue ( int x, bool[] list)
    y = count true in list
    return y >= x
4赞 2 revsMatt Joiner #49

在 C 中:

return !!a + !!b + !!c >= 2;

评论

0赞 Paul Wagland 9/20/2011
其实,这个答案是错误的......它应该是 >= 2,因为您至少需要两个真正的布尔值,而不是两个。
0赞 Matt Joiner 9/20/2011
@Paul Wagland:谢谢你的收获。
0赞 Matt Joiner 1/31/2012
@ergosys:我回答了两次?
0赞 Remi 9/8/2020
好东西。我更喜欢这个,因为它可以让你将其扩展到“四分之三”等。想知道是否有一个警告来计算真实的数量并将其与数量进行比较。
7赞 2 revs, 2 users 67%vine'th #50

我们可以将布尔值转换为整数并执行以下简单检查:

(int(a) + int(b) + int(c)) >= 2

评论

0赞 dargaud 12/14/2021
我不明白为什么这不是官方答案:它最简洁,执行速度最快,最容易理解。在 C 语言中,您不需要转类型:a+b+c>=2
2赞 2 revsSirensOfTitan #51

此问题的非简化解决方案是:

a'bc + abc' + abc + ab'c

减少使用 K-Maps,可以得到:

bc + ab + ac

可以通过在 a'bc 和 abc 最小项上使用 exclusive 或并结合 abc 和 ab'c 最小项来进一步减少这种情况:

b(a ^ c) + ac
2赞 3 revs, 3 users 50%d1val #52

怎么样 - Java,使用三个比较而不是 OP 的六个。(a||b) && (a||c)

错了,我应该早点检查。

评论

1赞 CCC 12/18/2014
这个是错误的。如果 a 为 true,而 b 和 c 为 false,则失败。
6赞 3 revs, 2 users 70%Bruce Attah #53

由于没有具体说明如何改进代码,我将努力改进代码,使其更有趣。这是我的解决方案:

boolean atLeastTwo(boolean t, boolean f, boolean True) {
    boolean False = True;
    if ((t || f) && (True || False)) 
        return "answer" != "42";
    if (t && f) 
        return !"France".contains("Paris");
    if (False == True) 
        return true == false;
    return Math.random() > 0.5;
}

如果有人想知道这段代码是否有效,这里有一个使用相同逻辑的简化:

boolean atLeastTwo(boolean a, boolean b, boolean c) {
    if ((a || b) && (c)) 
        return true;
    if (a && b) 
        return true;
    if (true) 
        return false;
    // The last line is a red herring, as it will never be reached:
    return Math.random() > 0.5; 

}

这可以进一步归结为以下几点:

return ((a || b) && (c)) || (a && b);

但现在它不再好笑了。

1赞 2 revs, 2 users 75%Kshitij Banerjee #54

如果我将布尔值转换为一个数字,并且该数字不是 2 的幂,则它至少有两个真。

a*4 + b*2 + c*1 = N
return( N != 0 && (N&(N-1)) != 0)

我只是给出一个替代方案。

0赞 2 revs, 2 users 73%Melvin Protacio #55

使用三元运算符解决问题的最简单形式是:

return a ? (b ? true : c) : (b ? c : false);

您可能还想通过使用对要求的双重否定来投资寻找解决方案,这意味着,您最多需要满足一个假值,而不是至少两个真值。

评论

0赞 Don Hatch 11/23/2021
看起来很像a ? b||c : b&&c
2赞 3 revsteodozjan #56

不是在性能的上下文中,而是在好的代码(可扩展和可读的代码,可以重用)

     static boolean trueBooleans (int howMany,boolean ... bools)
     {
      int total = 0;

      for (boolean b:bools)
        if (b && (++total == howMany)) return true;


      return false;
    }

以我的拙见,在编写 Java 时,易于处理意外更改和没有重复代码比简洁(脚本语言领域)或快速程序更重要。

0赞 3 revs, 3 users 65%Dhananjay #57

函数返回答案:ko

static int ho(bool a)
{
    return a ? 1 : 0;
}

static bool ko(bool a, bool b, bool c)
{
    return ho(a) + ho(b) + ho(c) >= 2;
}

评论

2赞 Jacklynn 5/20/2014
不需要 ?true :false。这告诉编译器,如果为 true,则返回 true,但如果为 false,则返回 false。去掉不必要的步骤,只返回 ho(a) + ho(b) + ho(c) >= 2;
1赞 binary_baba #58

这个怎么样:

(a - b) ? c : a

评论

0赞 Carlo Wood 1/1/2018
a != b ?C:A似乎更直观。
-6赞 2 revs, 2 users 75%user1883212 #59

我认为最简单的解决方案是:

return (a && b) || c;

评论

0赞 Luka 7/16/2013
这仅检查 a 和 b 是否都为 true,或者 c 是否为 true
1赞 mkobit #60

使用 Java 8 的 Stream 功能采取另一种方法,用于任意数量的具有任意所需数量的布尔值。如果 Stream 在处理所有元素之前达到限制,则会短路:

public static boolean atLeastTrue(int amount, Boolean ... booleans) {
    return Stream.of(booleans).filter(b -> b).limit(amount).count() == amount;
}

public static void main(String[] args){
    System.out.println("1,2: " + atLeastTrue(1, true, false, true));
    System.out.println("1,1: " + atLeastTrue(1, false, true));
    System.out.println("1,0: " + atLeastTrue(1, false));
    System.out.println("1,1: " + atLeastTrue(1, true, false));
    System.out.println("2,3: " + atLeastTrue(2, true, false, true, true));
    System.out.println("3,2: " + atLeastTrue(3, true, false, true, false));
    System.out.println("3,3: " + atLeastTrue(3, true, true, true, false));
}

输出:

1,2: true
1,1: true
1,0: false
1,1: true
2,3: true
3,2: false
3,3: true
0赞 To Kra #61
public static boolean atLeast(int atLeastToBeTrue, boolean...bools){
    int booleansTrue = 0;
    for(boolean tmp : bools){
        booleansTrue += tmp ? 1 : 0;
    }
    return booleansTrue >= atLeastToBeTrue;
}

你可以从a.k.a中选择你想要多少是真实的:-)at leastvarargsboolean[]

4赞 2 revscoder #62

目前使用 Java 8,我真的很喜欢这样的东西:

boolean atLeastTwo(boolean a, boolean b, boolean c) {
    return Stream.of(a, b, c).filter(active -> active).count() >= 2;
}

评论

0赞 Tunaki 11/10/2016
代替 ,您可以拥有 ...Arrays.asList(a, b, c).stream()Stream.of(a, b, c)
0赞 Boann 11/11/2016
非常重量级。
1赞 coder 11/17/2016
@Boan我认为代码揭示意图比早期优化更重要......
-1赞 nabil london #63

另一个:

return a? b||c : b&&c

评论

1赞 Kal 6/11/2020
接受答案的另一份副本?最好先检查一下你的答案是否已经被其他人发布。
0赞 2 revs, 2 users 76%Dupinder Singh #64

在算术运算的帮助下,这非常简单。

boolean a = true;
boolean b = false;
boolean c = true;

// Exactly one boolean value true.
return (a?1:0)+(b?1:0)+(c?1:0)==1;

// Exactly 2 boolean value true.
return (a?1:0)+(b?1:0)+(c?1:0)==2;

这就是您可以增加常量值以检查有多少布尔值的方法。true

0赞 Bobin #65

如果您有很多布尔值,则很容易遇到运算符重载。

operator fun Boolean.unaryPlus() = if (this) 1 else 0
// ...
if(+bool1 + +bool2 + ... + +boolN > 2) {
    // ...
}