比较两个二元向量

时间:2016-03-14 10:39:36

标签: c# arrays vector bitarray

我有两个比特阵,每个长度为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()似乎是我需要修复的一部分。等

5 个答案:

答案 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)

假设ab相等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);
}