C# 有人能给我解释一下这个GetCardinality方法在做什么吗?
我一直在用Lucene.NET研究分面搜索,我发现了一个很好的例子,它解释了相当多的内容,除了它完全忽略了检查位数组中项目基数的函数之外 有人能给我一个它正在做什么的概述吗?我不明白的主要事情是为什么按原样创建BitsSerray,它的用途,以及所有if语句在for循环中是如何工作的 这可能是一个很大的问题,但我必须先了解它是如何工作的,然后才能考虑在我自己的代码中使用它 谢谢C# 有人能给我解释一下这个GetCardinality方法在做什么吗?,c#,lucene.net,faceted-search,C#,Lucene.net,Faceted Search,我一直在用Lucene.NET研究分面搜索,我发现了一个很好的例子,它解释了相当多的内容,除了它完全忽略了检查位数组中项目基数的函数之外 有人能给我一个它正在做什么的概述吗?我不明白的主要事情是为什么按原样创建BitsSerray,它的用途,以及所有if语句在for循环中是如何工作的 这可能是一个很大的问题,但我必须先了解它是如何工作的,然后才能考虑在我自己的代码中使用它 谢谢 public static int GetCardinality(BitArray bitArray) {
public static int GetCardinality(BitArray bitArray)
{
var _bitsSetArray256 = new byte[] {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8};
var array = (uint[])bitArray.GetType().GetField("m_array", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(bitArray);
int count = 0;
for (int index = 0; index < array.Length; index ++)
count += _bitsSetArray256[array[index] & 0xFF] + _bitsSetArray256[(array[index] >> 8) & 0xFF] + _bitsSetArray256[(array[index] >> 16) & 0xFF] + _bitsSetArray256[(array[index] >> 24) & 0xFF];
return count;
}
publicstaticintgetcardinality(位数组位数组)
{
var _bitsetarray256=新字节[]{0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8};
var array=(uint[])bitArray.GetType().GetField(“m_array”,BindingFlags.NonPublic | BindingFlags.Instance).GetValue(bitArray);
整数计数=0;
for(int index=0;index>8)&0xFF]+\u位数组256[(数组[索引]>>16)&0xFF]+\u位数组256[(数组[索引]>>24)&0xFF];
返回计数;
}
使用值初始化\u bitsetarray 256
数组,使\u bitsetarray 256[n]
包含在n
的二进制表示中为0..255
中的n
设置的位数
例如,\u bitstarray256[13]
等于3,因为二进制中的13是1101
,其中包含31
s
这样做的原因是,预先计算并存储这些值要快得多,而不是每次(或按需)都要计算出来。毕竟,13的二进制表示形式中1
s的数量不会改变:)
在for
循环中,我们在一个uint
s数组中循环。C#uint
是一个32位的量,即由4个字节组成。我们的查找表告诉我们一个字节中设置了多少位,因此我们必须处理这四个字节中的每一个。count+=/code>行中的位操作提取这四个字节中的每一个,然后从查找数组中获取其位计数。将所有四个字节的位计数相加,得到整个uint
的位计数
因此,给定一个
位数组
,此函数将深入到uint[]m_array
成员,然后返回其中uint
的二进制表示形式中设置的总位数。我只是想为我们这些正在使用Lucene.net开发自己版本的Faceting的人发布一篇关于位数组的有用文章。请参阅:
这是对fastet方法的一个很好的解释,可以获得整数中on位的基数(这是上面代码示例所做的大部分)
在我的分面搜索和其他一些简单的更改中实现了本文中的方法,我能够将获取计数所需的时间缩短约65%。
不同之处在于:
private static int[] _bitcounts = InitializeBitcounts();
private static int GetCardinality(BitArray bitArray)
{
uint[] array = (uint[])bitArray.GetType().GetField("m_array", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(bitArray);
int count = 0;
foreach (uint value in array)
{
count += _bitcounts[value & 65535] + _bitcounts[(value >> 16) & 65535];
}
return count;
}
private static int[] InitializeBitcounts()
{
int[] bitcounts = new int[65536];
int position1 = -1;
int position2 = -1;
//
// Loop through all the elements and assign them.
//
for (int i = 1; i < 65536; i++, position1++)
{
//
// Adjust the positions we read from.
//
if (position1 == position2)
{
position1 = 0;
position2 = i;
}
bitcounts[i] = bitcounts[position1] + 1;
}
return bitcounts;
}
private static int[]_bitcounts=InitializeBitcounts();
私有静态int GetCardinality(位数组位数组)
{
uint[]数组=(uint[])位数组.GetType().GetField(“m_数组”,BindingFlags.NonPublic | BindingFlags.Instance).GetValue(位数组);
整数计数=0;
foreach(数组中的uint值)
{
计数+=(u bitcounts[value&65535]+(value>>16)&65535];
}
返回计数;
}
私有静态int[]初始化EBITCounts()
{
int[]位计数=新的int[65536];
int位置1=-1;
int位置2=-1;
//
//循环遍历所有元素并分配它们。
//
对于(int i=1;i<65536;i++,位置1++)
{
//
//调整我们从中读取的位置。
//
如果(位置1==位置2)
{
位置1=0;
位置2=i;
}
位计数[i]=位计数[1]+1;
}
返回比特数;
}
太棒了,谢谢你,阿卡什。有些事情我仍然想不起来,但至少我理解这个方法的概念,以及它到底在做什么。