xor with 3 values

后端 未结 10 1438
野性不改
野性不改 2020-12-30 22:12

I need to do an xor conditional between 3 values, ie i need one of the three values to be true but not more than one and not none.

I thought i could use the xor ^ op

相关标签:
10条回答
  • 2020-12-30 22:36

    Came across this while I went down the wrong path trying to solve my own problem (XOR across 4 values); decided that LINQ is the simplest way to handle this problem for an N-case;

    bool OneAndOnlyOneIsTrue(IEnumerable<bool> conditions)
    {
        return conditions.Count(c => c) == 1;
    }
    

    Invoked like;

    bool OneLuckyGuy(Person p1, Person p2, Person p3, Person p4)
    {
         return OneAndOnlyOneIsTrue(new [] {         
             p1.IsAMan(),
             p2.IsAMan(),
             p3.IsAMan(),
             p4.IsAMan()
         });
    }
    

    Instruction-wise, this will check each condition once, so function is O(n), but it's flexible and a damn site more readable than the bitwise alternative. ;-)

    0 讨论(0)
  • 2020-12-30 22:37

    XOR is a binary operator, it can only be used on 2 values at a time. So when you do (true XOR true XOR true), it actually does ((true XOR true) XOR true)...

    The inner (true XOR true) resolves to false because they're the same. With that resolved, the remainder is (false XOR true), which resolves to true.

    It sounds like you're trying to be clever or super-efficient about matching your conditions. This would probably take me several minutes to puzzle out and then write a truth-table or test to make sure it treats all possible combinations correctly.

    It is so much simpler to just count how many of them are true and do if (countTrues == 1). The reason for this is that it doesn't have significant overhead, and it is actually readable and understandable compared to a solution using only bit-twiddling (there are a couple other answers here that demonstrate it).

    0 讨论(0)
  • 2020-12-30 22:39

    ((true ^ true) ^ true) will return true, which is not what you would expect from true ^ true ^ true.

    To make sure that you get the outcome you want (only one value to be true) do the following:

    if ((a && !b && !c) || (!a && b && !c) || (!a && !b && c))
    

    Alternatively, based on @jcomeau_ictx answer, you can do the following:

    if( Convert.ToInt32(a) + Convert.ToInt32(b) + Convert.ToInt32(c) == 1 )
    

    Or, you could create a function:

    public bool TernaryXor(bool a, bool b, bool c)
    {
        //return ((a && !b && !c) || (!a && b && !c) || (!a && !b && c));
    
        // taking into account Jim Mischel's comment, a faster solution would be:
        return (!a && (b ^ c)) || (a && !(b || c));
    }
    

    EDIT: You might want to name the function TernaryXor so that it is more clear as to the outcome of the function.

    0 讨论(0)
  • 2020-12-30 22:40

    the solution simple it's

    a = true; b = false; c = true
    
    (a ^ b) || (a ^ c)
    
    0 讨论(0)
提交回复
热议问题