sia*_*ana 26 c# conditional operators
我需要在3个值之间做一个xor条件,即我需要三个值中的一个为真但不超过一个而不是没有.
我以为我可以使用xor ^运算符,但它没有按预期工作.
我预计这会返回假,但它不会.(true ^ true ^ true)
所有其他组合似乎按我的预期工作.
在查看xor运算符的文档时,他们只讨论比较2个值,并且我无法在线查找3个或更多值的任何内容.
任何人都可以放弃任何亮点或建议一个简单的方法吗?
Chr*_*ris 11
((true ^ true) ^ true)
将返回true
,这不是你所期望的true ^ true ^ true
.
要确保获得所需的结果(只有一个值为true),请执行以下操作:
if ((a && !b && !c) || (!a && b && !c) || (!a && !b && c))
Run Code Online (Sandbox Code Playgroud)
或者,根据@jcomeau_ictx答案,您可以执行以下操作:
if( Convert.ToInt32(a) + Convert.ToInt32(b) + Convert.ToInt32(c) == 1 )
Run Code Online (Sandbox Code Playgroud)
或者,您可以创建一个函数:
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));
}
Run Code Online (Sandbox Code Playgroud)
编辑:您可能想要命名该函数,TernaryXor
以便更清楚该函数的结果.
这肯定是一个棘手的问题。鉴于你想要的:
a b c rslt
0 0 0 0
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
Run Code Online (Sandbox Code Playgroud)
这将做到:
rslt = (!a & (b ^ c)) || (a & !(b | c));
Run Code Online (Sandbox Code Playgroud)
第一部分处理 wherea
为 0的四种情况。 第二部分, wherea
不为 0。
一种更简单的方式来看待它是这样的:
rslt = (a | b | c) & !((a & b) | (a & c) | (b & c))
Run Code Online (Sandbox Code Playgroud)
也就是说,三个中的一个必须是真的,但没有两个(或更多)是真的。
似乎应该有一种方法可以进一步简化,但没有想到。也许我需要更多的咖啡因。
编辑
我认为这是我今天早上正在寻找的解决方案:
rslt = a ? !(b | c) : (b ^ c);
Run Code Online (Sandbox Code Playgroud)
现在,至于为什么我使用|
而不是||
:
这是风格问题和对分支的旧偏见的结合(旧习惯很难改掉)。 !(b | c)
生成此 IL 代码:
ldarg.1
ldarg.2
or
ldc.i4.0
ceq
stloc.0
Run Code Online (Sandbox Code Playgroud)
该代码中没有任何分支。如果我使用||
,如在 中!(b ||c)
,它会生成:
ldarg.1
brfalse.s IL_009B
ldarg.2
br.s IL_009C
IL_009B:
ldc.i4.1
IL_009C:
stloc.0
Run Code Online (Sandbox Code Playgroud)
其中有两个分支。我不知道 JIT 生成的代码是否会反映这一点,但我怀疑它会。所以一位代码是 6 条总是被执行的指令。另一个是6条指令,有时只执行4条。但是分支惩罚很可能会消耗不执行两条指令的任何收益。
我意识到现代 CPU 在分支方面比 8086 好得多,并且这两个代码片段的运行时可能没有任何可检测的差异。即使有,也不可能对我通常编写的程序的整体运行时间产生重大影响。
但我告诉你,它肯定曾经使用过!在分支非常昂贵的 8086 上,(b | c)
和之间的差异(b || c)
是巨大的。
最后,|
正如您所指出的,使用 强制对整个表达式进行评估。我的原始代码实际上说,“如果这个表达式为真或那个表达式为真。” 使用&&
并将||
其变成一堆条件,在我的脑海中,更难阅读。
所以:基于最可能过时的性能考虑的旧偏见。但无害。
但是,必须小心,(b() | c())
除非必须评估两个函数,否则不要编写类似的东西。
归档时间: |
|
查看次数: |
11202 次 |
最近记录: |