Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 检查三分之二的布尔值是否为真_Java_Boolean_Boolean Logic - Fatal编程技术网

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

Java 检查三分之二的布尔值是否为真,java,boolean,boolean-logic,Java,Boolean,Boolean Logic,最近一位采访者问我这样一个问题:给定三个布尔变量a、b和c,如果三个变量中至少有两个为真,则返回真 我的解决办法如下: boolean atLeastTwo(boolean a, boolean b, boolean c) { if ((a && b) || (b && c) || (a && c)) { return true; } else{ return false; } }

最近一位采访者问我这样一个问题:给定三个布尔变量a、b和c,如果三个变量中至少有两个为真,则返回真

我的解决办法如下:

boolean atLeastTwo(boolean a, boolean b, boolean c) {
    if ((a && b) || (b && c) || (a && c)) {
        return true;
    }
    else{
        return false;
    }
}
他说这可以进一步改进,但是如何改进呢?

而不是写:

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) {
    if (a) {
        return b||c;
    } 
    else {
        return b&&C;
    }
或者这个(无论你觉得哪个更容易掌握):

它只测试
a
b
一次,最多测试
c

工具书类

    • 为什么不按字面意思实施呢?:)

      在C语言中,您可以只编写
      a+b+C>=2
      (或者
      !!a+!!b+!!C>=2
      ,这样非常安全)

      为了响应ToBubeer对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);
              }
          }
      }
      
      以后的迭代:

      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
      
      我想知道,在(a+b+c>=2)的情况下,java虚拟机可以做些什么来降低性能

      下面是使用
      -client
      VM开关运行java时发生的情况:

      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
      
      神秘

      如果我运行它,它会慢近100倍,但是
      a&&b | b&&c | a&&c
      版本会赢

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

      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
      

      最明显的改进包括:

      // 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));
      }
      

      但是这些改进是很小的。

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

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


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

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

      int howManyBooleansAreTrue =
            (a ? 1 : 0)
          + (b ? 1 : 0)
          + (c ? 1 : 0);
      
      return howManyBooleansAreTrue >= 2;
      
      int two(int a, int b, int c) {
        return !a + !b + !c < 2;
      }
      

      这类问题可以通过以下方法解决:

      由此推断,第一行需要一个组,第一列需要两个组,以获得多基因润滑油的最佳解决方案:

      (C && (A || B)) || (A && B)  <---- first row
             ^
             |
         first column without third case
      
      (C&&(A | | | B))| |(A&&B)在这里获取答案(到目前为止):

      并通过反编译器运行它们(javap-cx>results.txt):

      从“X.java”编译而来
      公共类X扩展了java.lang.Object{
      公共X();
      代码:
      0:aload_0
      1:invokespecial#1;//方法java/lang/Object。“:()V
      4:返回
      静态布尔a(布尔、布尔、布尔);
      代码:
      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:我轮到你了
      静态布尔b(布尔、布尔、布尔);
      代码:
      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:转到33
      32:iconst_0
      33:我轮到你了
      静态布尔c(布尔,布尔,布尔);
      代码:
      0:iload_0
      1:iload_1
      2:土地
      3:iload_1
      4:iload_2
      5:土地
      6:ior
      7:iload_2
      8:iload_0
      9:土地
      10:ior
      11:我轮到你了
      静态布尔d(布尔、布尔、布尔);
      代码:
      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:转到18
      17:iconst_0
      18:iadd
      19:iload_2
      20:ifeq 27
      23:iconst_1
      24:转到28
      27:iconst_0
      28:iadd
      29:iconst_2
      30:if_icmplt 37
      33:iconst_1
      34:转到38
      37:iconst_0
      38:我轮到你了
      }
      
      您可以看到?:的版本比您的原始版本的固定版本稍好一些。最好的方法是完全避免分支。从指令更少(大多数情况下)的角度来看,这是好的,对于CPU的分支预测部分来说更好,因为分支预测中的错误猜测可能会导致CPU暂停

      我认为最有效的一个是来自moonshadow的。它平均使用最少的指令,减少了CPU中管道暂停的机会

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


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

      另一个直接代码示例:

      boolean atLeastTwo(boolean a, boolean b, boolean c) 
      {
        return ((a && b) || (b && c) || (a && c));
      }
      
      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的比较快(或者更少),那么这可能会运行得稍快一些。

      这里是一种测试驱动的通用方法。目前提供的大多数解决方案都不那么“高效”,但它们清晰、经过测试、有效且通用

      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;
          }
      }
      

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

      创建布尔值数据库:

      db.values.insert({value: true});
      db.values.insert({value: false});
      db.values.insert({value: true});
      
      创建地图,减少功能:

      编辑:我喜欢将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;
      }
      

      还有另一种方法,但不是很好:

      return (Boolean.valueOf(a).hashCode() + Boolean.valueOf(b).hashCode() + Boolean.valueOf(c).hashCode()) < 3705);
      
      return(Boolean.valueOf(a).hashCode()+Boolean.valueOf(b.hashCode()+Boolean.valueOf(c.hashCode())<3705);
      
      Boolean
      hashcode值固定为1231表示真,1237表示假,因此同样可以使用最简单的方法(IMO),不易混淆且易于阅读:

      // Three booleans, check if two or more are true
      
      return ( a && ( b || c ) ) || ( b && c );
      
      做这件事的方法太多了…

      我不喜欢三元(
      返回a?(b
      
      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;
      }
      
      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;
      }
      
      return (Boolean.valueOf(a).hashCode() + Boolean.valueOf(b).hashCode() + Boolean.valueOf(c).hashCode()) < 3705);
      
      // Three booleans, check if two or more are true
      
      return ( a && ( b || c ) ) || ( b && c );
      
      Function ReturnTrueIfTwoIsTrue(bool val1, val2, val3))
      {
           return (System.Convert.ToInt16(val1) +
                   System.Convert.ToInt16(val2) +
                   System.Convert.ToInt16(val3)) > 1;
      }
      
      boolean atLeastTwo(boolean a, boolean b, boolean c) {
          if (a) {
              return b||c;
          } 
          else {
              return b&&C;
          }
      
      return a ^ b ? c : a
      
      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;
      }
      
      return 1 << $a << $b << $c >= 1 << 2;
      
        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
      
      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;
      }
      
      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;
      }
      
      (defn at-least [n & bools]
        (>= (count (filter true? bools)) n)
      
      (at-least 2 true false true)
      
      return (a & b) | (c & (a ^ b));
      
      return (a==b) ? a : c;
      
      static boolean five(final boolean a, final boolean b, final boolean c)
      {
          return a == b ? a : 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
      
      one                5242 ms
      two                6318 ms
      three (moonshadow) 3806 ms
      four               7192 ms
      five  (pdox)       3650 ms
      
      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.
      
      return !!a + !!b + !!c >= 2;
      
      (int(a) + int(b) + int(c)) >= 2
      
      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);