有效地比较比特(x的重叠集)

时间:2015-11-29 00:46:44

标签: c#

我想将任意长度的比特流与c#中的掩码进行比较,并返回多少比特相同的比率。 要检查的掩码是2位到8k之间的任何位置(90%的掩码是5位长),输入可以是2位到~500k之间的任何位置,平均输入字符串为12k(但是,是的,大部分时间它将比较5位与12k的前5位

现在,我天真的实现将是这样的:

bool[] mask = new[] { true, true, false, true };
float dendrite(bool[] input) { 
    int correct = 0;
    for ( int i = 0; i<mask.length; i++ ) { 
        if ( input[i] == mask[i] ) 
            correct++;
    }
    return (float)correct/(float)mask.length;
}

但我希望通过某种二元运算符魔法可以更好地处理(更高效)?

有人有任何指示?

编辑:我的设计中此时数据类型并未固定,因此如果整数或字节数更好,我也是一个快乐的露营者,尝试优化效率,计算越快,越好。

例如,如果你能让它像这样工作:

int[] mask = new[] { 1, 1, 0, 1 };
float dendrite(int[] input) { 
    int correct = 0;
    for ( int i = 0; i<mask.length; i++ ) { 
        if ( input[i] == mask[i] ) 
            correct++;
    }
    return (float)correct/(float)mask.length;
}

或者这个:

int mask = 13; //1101
float dendrite(int input) { 

    return // your magic here;
} // would return 0.75 for an input 
  // of 101 given ( 1100101 in binary, 
  // matches 3 bits of the 4 bit mask == .75 

解答: 我把每个建议的答案都互相对决,而Fredou和Marten的解决方案并没有得到应对,但Fredou最终提交了最快最精简的解决方案。当然,由于实现之间的平均结果差别很大,我可能不得不在稍后重新阅读这篇文章。 :)但那可能只是我弄乱了我的测试脚本。 (我希望,现在为时已晚,上床睡觉=)

sparse1.Cyclone
1317ms   3467107ticks 10000iterations
result:    0,7851563

sparse1.Marten
288ms   759362ticks 10000iterations
result:    0,05066964

sparse1.Fredou
216ms   568747ticks 10000iterations
result:    0,8925781

sparse1.Marten
296ms   778862ticks 10000iterations
result:    0,05066964

sparse1.Fredou
216ms   568601ticks 10000iterations
result:    0,8925781

sparse1.Marten
300ms   789901ticks 10000iterations
result:    0,05066964

sparse1.Cyclone
1314ms   3457988ticks 10000iterations
result:    0,7851563

sparse1.Fredou
207ms   546606ticks 10000iterations
result:    0,8925781

sparse1.Marten
298ms   786352ticks 10000iterations
result:    0,05066964

sparse1.Cyclone
1301ms   3422611ticks 10000iterations
result:    0,7851563

sparse1.Marten
292ms   769850ticks 10000iterations
result:    0,05066964

sparse1.Cyclone
1305ms   3433320ticks 10000iterations
result:    0,7851563

sparse1.Fredou
209ms   551178ticks 10000iterations
result:    0,8925781

(在这里复制的试样,如果我摧毁了你的修改它,知道。https://dotnetfiddle.net/h9nFSa

3 个答案:

答案 0 :(得分:1)

我会将代码更改为以下内容:

// hardcoded bitmask
byte mask = 255; 
float dendrite(byte input) { 
  int correct = 0;

  // store the xor:ed result
  byte xored = input ^ mask;

  // loop through each bit 
  for(int i = 0; i < 8; i++) {
    // if the bit is 0 then it was correct
    if(!(xored & (1 << i)))
      correct++;
   }
   return (float)correct/(float)mask.length;
}

以上使用掩码和8位输入,但当然你可以修改它以使用4字节整数,依此类推。

不确定这是否会按预期工作,但它可能会为您提供一些有关如何继续的线索。

例如,如果您只想检查前4位,可以将代码更改为:

float dendrite(byte input) { 
  // hardcoded bitmask i.e 1101
  byte mask = 13;  
  // number of bits to check
  byte bits = 4;

  int correct = 0;

  // store the xor:ed result
  byte xored = input ^ mask;

  // loop through each bit, notice that we only checking the first 4 bits
  for(int i = 0; i < bits; i++) {
    // if the bit is 0 then it was correct
    if(!(xored & (1 << i)))
      correct++;
   }
   return (float)correct/(float)bits;
}

当然,实际使用int代替byte可能会更快。

答案 1 :(得分:1)

我想出了这段代码:

Get-ADComputer -Filter * | Select-Object -ExpandProperty Name | Out-File .\ADcomputers.txt

$LaunchLine = 'powershell.exe -Version 4.0 -Command "& {netsh advfirewall set allprofiles state off}"'
$Appfilter = 'powershell.exe -Version 4.0 -Command "& {Get-NetFirewallApplicationFilter -program * | fl program}"'
$ComputerList = Get-Content .\adcomputers.txt

foreach($Computer in $ComputerList) {
    [String]$wmiPath = "\\{0}\root\cimv2:win32_process" -f $computer

    try {
        [wmiclass]$Executor = $wmiPath
        $executor.Create($LaunchLine, $Appfilter)
    } catch {
        Add-Content offComp&programsALLO.txt "computers:$Computer, $Appfilter "
    }
}

这将一次检查64位。如果您需要更多,您可以将输入数据拆分为64位字,并逐个进行比较,计算平均结果。

这是一个.NET代码和工作测试用例的小提琴:
https://dotnetfiddle.net/5hYFtE

答案 2 :(得分:1)

code

怎么样?
using System;

namespace ConsoleApplication1
{
    public class Program
    {
        public static void Main(string[] args)
        {
            int a = Convert.ToInt32("0001101", 2);
            int b = Convert.ToInt32("1100101", 2);

            Console.WriteLine(dendrite(a, 4, b));

        }

        private static float dendrite(int mask, int len, int input)
        {
            return  1 - getBitCount(mask ^ (input & (int.MaxValue >> 32 - len))) / (float)len;            
        }

        private static int getBitCount(int bits)
        {
            bits = bits - ((bits >> 1) & 0x55555555);
            bits = (bits & 0x33333333) + ((bits >> 2) & 0x33333333);
            return ((bits + (bits >> 4) & 0xf0f0f0f) * 0x1010101) >> 24;
        }
    }
}

64位一this one - dotnetfiddle example

using System;

namespace ConsoleApplication1
{
    public class Program
    {
        public static void Main(string[] args)
        {
            //                                                                                      1
            ulong a = Convert.ToUInt64("0000000000000000000000000000000000000000000000000000000000001101", 2);
            ulong b = Convert.ToUInt64("1110010101100101011001010110110101100101011001010110010101100101", 2);

            Console.WriteLine(dendrite(a, 4, b));

        }

        private static float dendrite(ulong mask, int len, ulong input)
        {
            return 1 - getBitCount(mask ^ (input & (ulong.MaxValue >> (64 - len)))) / (float)len;            
        }

        private static ulong getBitCount(ulong bits)
        {
            bits = bits - ((bits >> 1) & 0x5555555555555555UL);
            bits = (bits & 0x3333333333333333UL) + ((bits >> 2) & 0x3333333333333333UL);
            return unchecked(((bits + (bits >> 4)) & 0xF0F0F0F0F0F0F0FUL) * 0x101010101010101UL) >> 56;
        }
    }
}