分组偶数和奇数

c#

我正在学习 Linq 以及如何对事物进行分组,我正在查看我以前的解决方案,我发现了这一点:

public IList<IGrouping<int, int>> GroupEvenAndOddNumbers(int[] numbers)
{
    return numbers.ToLookup(x => x & 1).ToList();
}

这与我一直在进行分组的方式背道而驰,但我找不到用正常方式进行分组的方法。问题是我不明白为什么会这样,这应该不是问题,但是知道为什么会这样仍然很好。我不明白的部分是“x & 1”部分。这里应用了什么逻辑?

回答

奇偶校验(奇/偶)

奇偶校验和二进制数之间存在有趣的相互作用。所有奇数都以 结尾1,所有偶数都以 结尾0

想想十进制系统,以10 为底。你怎么知道一个东西能被10整除因为它以0结尾。
这适用于每个基地。在基数 8(八进制)中,可被 8 整除的数以 0 结尾。在基数 16(十六进制)中,可被 16 整除的数以 0 结尾。在基数 12345 中,所有可被 12345 整除的数以 0 结尾。选择任意数字,它总是有效。

在基数 2(二进制)中,可以被 2 整除的数字(= 偶数,根据定义)以 0 结尾。

&是按位与运算符。简而言之,您向它传递两个二进制值,并且对于同一位置的每个数字,它都会进行digitA AND digitB评估。结果是这些AND评估的价值。

首先,AND只有当两个输入都为真时,评估才返回真。如果至少有一个是假的,那么结果肯定也是假的。

输入 A 输入 B 结果
0 0 0
1 0 0
0 1 0
1 1 1

现在让我们看看两个随机二进制数,对于每个数字位置,找出 AND 结果是什么。

         10110100
         10001011
 -[AND]------------
         10000000

注意只有在最左边的位置,两个位都是 1(真),因此结果也是 1(真)。在所有其他位置,两个输入数字之一始终为 0(假),因此结果为 0(假)

现在让我们看一个特殊情况。我将隐藏第一个数字,只显示第二个数字。试着算出你已经能猜到多少结果。

         ????????
         00000001
 -[AND]------------
         ????????

似乎不可能,对吧?好吧,让我们考虑一下。在任何位置,如果至少有一个 0,结果肯定是 0。即使我们不知道第一个数字,但第二个数字已经表明前 7 位数字的位置肯定会导致一个 0,因为第二个number 已经通过在这些位置具有 0 来强制执行此操作。

所以现在我们知道了:

         ????????
         00000001
 -[AND]------------
         0000000?

让我们想想最后一个数字。什么时候是1,什么时候是0?在阅读下面的答案之前,请考虑一下

如果第一个数字以 0 结尾,则结果也将以 0 结尾,因为0 AND 1 = 0.
如果第一个数字以 1 结尾,则结果也将以 1 结尾,因为1 AND 1 = 1

还记得我们之前说过的话吗?在二进制中,所有奇数都以 结尾1,所有偶数都以 结尾0。所以我们可以重写我们之前的结论来说明以下内容:

如果第一个数字是偶数,结果也会以 0 结尾,因为0 AND 1 = 0.
如果第一个数字是奇数,结果也会以 1 结束,因为1 AND 1 = 1

我们可以颠倒这个逻辑:

如果结果以 0 结尾,则第一个数字是even
如果结果以 1 结尾,则第一个数字为奇数

编码

numbers.ToLookup(x => x & 1).ToList()

ToLookup本质上是一个 group by 语句。它将具有相同计算值的所有元素分组在同一组中。这些组是根据计算值制作的x & 1

这里只有两个可能的组。使用我们的演示值,结果是0000000000000001(因为前 7 位数字始终为 0,最后一位数字可能不同)。

在标记为 的组中00000000,您将找到所有以 a 结尾的数字0,这些数字都是偶数
在标记为 的组中00000001,您将找到所有以 a 结尾的数字1,这些数字都是奇数

组的标签并不重要。这里重要的是您现在已经正确地分离了 evens 和 ods


这里还有其他可能的解决方案,但它们都归结为相同的原则。另一个例子是

var evenNumbers = numbers.Where(x => x % 2 == 0).ToList();
var oddNumbers  = numbers.Where(x => x % 2 == 1).ToList();

但是,位逻辑的性能往往稍高一些。这是以位逻辑相当困难为代价的,但在寻找数字奇偶性(偶数/奇数)这样简单的情况下,性能增益值得稍微复杂一些。


以上是分组偶数和奇数的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>