Elegantly determine if more than one boolean is “t

2019-01-13 05:26发布

I have a set of five boolean values. If more than one of these are true I want to excecute a particular function. What is the most elegant way you can think of that would allow me to check this condition in a single if() statement? Target language is C# but I'm interested in solutions in other languages as well (as long as we're not talking about specific built-in functions).

One interesting option is to store the booleans in a byte, do a right shift and compare with the original byte. Something like if(myByte && (myByte >> 1)) But this would require converting the separate booleans to a byte (via a bitArray?) and that seems a bit (pun intended) clumsy... [edit]Sorry, that should have been if(myByte & (myByte - 1)) [/edit]

Note: This is of course very close to the classical "population count", "sideways addition" or "Hamming weight" programming problem - but not quite the same. I don't need to know how many of the bits are set, only if it is more than one. My hope is that there is a much simpler way to accomplish this.

22条回答
混吃等死
2楼-- · 2019-01-13 05:40

If you only have five different values, you can easily do the test by packing the bits in to a short or an int and checking to see if it is any of the zero or one bit answers. The only invalid numbers you could get would be..

0x 0000 0000 
0x 0000 0001
0x 0000 0010
0x 0000 0100
0x 0000 1000
0x 0001 0000

This gives you six values to search for, put them in a lookup table and if it's not in there, you have your answer.

This gives you a simple answer.

   public static boolean moreThan1BitSet(int b)
   {
      final short multiBitLookup[] = { 
            1, 1, 1, 0, 1, 0, 0, 0,
            1, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0,
            1, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0
      };
      if(multiBitLookup[b] == 1)
         return false;
      return true;
   }

This doesn't scale well past 8 bits, but you only have five.

查看更多
别忘想泡老子
3楼-- · 2019-01-13 05:41

If your flags are packed into one word then Michael Burr's solution will work. However, the loop is not necessary:

int moreThanOneBitSet( unsigned int v)
{
    return (v & (v - 1)) != 0;
}

example

 v (binary) | v - 1 | v&(v-1) | result
------------+-------+---------+--------
       0000 |  1111 |    0000 |  false
       0001 |  0000 |    0000 |  false
       0010 |  0001 |    0000 |  false
       0011 |  0010 |    0010 |   true
       .... |  .... |    .... |   ....
       1000 |  0111 |    0000 |  false
       1001 |  1000 |    1000 |   true
       1010 |  1001 |    1000 |   true
       1011 |  1010 |    1010 |   true
       1100 |  1011 |    1000 |   true
       1101 |  1100 |    1100 |   true
       1110 |  1101 |    1100 |   true
       1111 |  1110 |    1110 |   true
查看更多
▲ chillily
4楼-- · 2019-01-13 05:44

Not exactly pretty... but here's another way to do it:

if (
    (a && (b || c || d || e)) ||
    (b && (c || d || e)) ||
    (c && (d || e)) ||
    (d && e)
)
查看更多
欢心
5楼-- · 2019-01-13 05:45

It's time for the obligatory LINQ answer, which in this case is actually quite neat.

var bools = new[] { true, true, false, false, false };

return bools.Count(b => b == true) > 1;
查看更多
趁早两清
6楼-- · 2019-01-13 05:45

I was recently having this same issue, where I had three boolean values, which I needed to check that only 1 of them was true at a time. For this I used the xor operator as follows:

bool a = true;
bool b = true;
bool c = false;

if (a || b || c)
{
    if (a ^ b ^ c){
        //Throw Error
    }
}

This code will throw an error as a and b are both true.

For reference: http://www.dotnetperls.com/xor

I have only just found the xor operator in C# if anyone knows of any pit falls of this strategy, please let me know.

查看更多
可以哭但决不认输i
7楼-- · 2019-01-13 05:49

if you mean more than or equal to one boolean equals to true, you could do it like

if (bool1 || bool2 || bool3 || bool4 || bool5)

If you need more than one (2 and above) booleans equal to true, you can try

int counter = 0;
if (bool1) counter++;
if (bool2) counter++;
if (bool3) counter++;
if (bool4) counter++;
if (bool5) counter++;
if (counter >= 2) //More than 1 boolean is true
查看更多
登录 后发表回答