我有两个比特阵,每个长度为200.000。我需要在同一个订单中查找每个列表中有多少1个。让我画出来:
1 0
**1 1**
0 0
0 1
0 0
**1 1**
1 0
0 1
.. ..
所以结果应该是2。
我在两次嵌套中进行了这种比较 - 大约2000万次:)。
我现在用bitarray和&运算符而不是使用popCount方法来查找结果。
那你对这类问题有什么建议呢?你会在哪里存储这些向量,你会如何以我想要的方式比较它们?我需要速度。
更新 我用760长度阵列完成了这个,用我的方法花了不到5秒。评论中建议的每个方法都花了> 1分钟(我停止了程序) 所以我想我的是谁必须回答它。我简化了我的代码。
for(i<761)
var vector1 = matris[getvectorthing];
for(j=i+1<761)
{
var vector2 = matris[getvectorthing];
var similarityResult = vector1Temp.And(vector2);
var similarityValuePay = popCount(similarityResult);
//similarityValuePay is result that i want
}
}
private static int popCount(BitArray simRes)
{
Int32[] ints = new Int32[(simRes.Count >> 5) + 1];
simRes.CopyTo(ints, 0);
Int32 count = 0;
// fix for not truncated bits in last integer that may have been set to true with SetAll()
ints[ints.Length - 1] &= ~(-1 << (simRes.Count % 32));
var tempInt = ints.Where(k => k != 0).ToArray();
for (Int32 i = 0; i < tempInt.Length; i++)
{
Int32 c = tempInt[i];
// magic (http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel)
unchecked
{
c = c - ((c >> 1) & 0x55555555);
c = (c & 0x33333333) + ((c >> 2) & 0x33333333);
c = ((c + (c >> 4) & 0xF0F0F0F) * 0x1010101) >> 24;
}
count += c;
}
return count;
}
我问它,因为可能有很多切割方法或简单的调整,以使性能更好。例如:
var tempInt = ints.Where(k => k != 0).ToArray();
这个ToArray()似乎是我需要修复的一部分。等
答案 0 :(得分:2)
使用And
方法,并计算true
,我认为这比其他答案更快。
var bit1 = new BitArray(new bool[]{true, false, ...});
var bit2 = new BitArray(new bool[]{false, false, ...});
var and = bit1.And(bit2);
var result = 0; //Total count I think you want.
for (int i = 0; i < and.Length; i++)
{
if (and[i])
{
result++;
}
}
<强>更新强>
我想出了一个提高绩效的解决方案。
将popCount
替换为:
private static int popCount(BitArray simRes)
{
Int32[] ints = new Int32[(simRes.Count >> 5) + 1];
simRes.CopyTo(ints, 0);
Int32 count = 0;
// fix for not truncated bits in last integer that may have been set to true with SetAll()
ints[ints.Length - 1] &= ~(-1 << (simRes.Count % 32));
for (Int32 i = 0; i < ints.Length; i++)
{
Int32 c = ints[i];
if (c == 0)
{
continue;
}
// magic (http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel)
unchecked
{
c = c - ((c >> 1) & 0x55555555);
c = (c & 0x33333333) + ((c >> 2) & 0x33333333);
c = ((c + (c >> 4) & 0xF0F0F0F) * 0x1010101) >> 24;
}
count += c;
}
return count;
}
在我的机器中,当simRes.Length > 16000000
时,if(c == 0){...}
块会提供良好的性能。但是,当simRes.Length < 16000000
时,应删除if(c == 0){...}
块。
答案 1 :(得分:1)
您可以使用And()
方法
BitArray ba = new BitArray(new bool[] { true, true, false, false, false, true, true, false });
BitArray ba2 = new BitArray(new bool[] { false, true, false, true, false, true, false, true });
int result = ba.And(ba2).Cast<bool>().Count(x => x); //2
答案 2 :(得分:0)
假设a
和b
相等Length
。
int[] a = new[] {1,0,1, ...};
int[] b = new[] {0,0,1, ...};
int c = 0;
for (int i = 0; i < a.Length; i++)
c += a[i] == 1 && b[i] == 1 ? 1 : 0;
简单。时间复杂度为 O(n),其中 n 是数组中的多个元素。
答案 3 :(得分:0)
更简洁的答案:
bool[] A = ...;
bool[] B = ...;
var result = A.Where((val, ix)=>val && B[ix]).Count();
答案 4 :(得分:-2)
static void Main()
{
var a = new BitArray(new bool[]{true, false,true});
var b = new BitArray(new bool[]{false, false,true});
int result = 0;
int size = Math.Min( a.Length, b.Length); //or a.Length or 200000
for (int i = 0; i < size ; i++)
{
if (a[i] == true && b[i] == true )
{
result++;
}
}
Console.WriteLine("{0}",result);
}