如何确定设置哪个位

时间:2011-03-30 09:25:09

标签: c# bit

我有两个字节,它们只有1位不同。我想知道这是什么。

所以:

byte a,b;
a=0;
b=2;

ChangedBit(a,b) should give bit 1
ChangedBit(4,5) should give bit 0
ChangedBit(7,3) should give bit 2

非常欢迎任何建议!!

谢谢,

埃里克

7 个答案:

答案 0 :(得分:2)

如果它们相差一点,xor应该给你 那个位。那么你可以转而找到哪个?

或许需要一些优化:

static int ChangedBit(int x, int y)
{
    uint bits = (uint)(x ^ y); // need uint to avoid backfill with shift
    int count = -1;
    while (bits != 0)
    {
        count++;
        bits >>= 1;
    }
    return count;        
}

答案 1 :(得分:2)

正确的解决方案是

var bit = Math.Log(a ^ b, 2);

尽管如此,如果出于任何原因 more 而不是一位不同,这会留下一个问题。

您可以使用

var bit = (int)Math.Log(a ^ b, 2);

为了获得最高不同位的索引,如果有多个不同的话。

警告:为了正确起见,任何此类函数在尝试提供结果之前还应检查两个参数ab是否实际不同。否则你将得到一个毫无意义的结果或一个彻头彻尾的例外。这适用于此处提供的所有解决方案,包括此解决方案。

答案 2 :(得分:1)

你可以很容易地做到这一点:

Math.Log(Math.Abs(a-b), 2)

更新:修复......

答案 3 :(得分:1)

如果您可以从零开始计算,则Math.Log(a^b,2)完成工作

答案 4 :(得分:1)

var dif = a ^ b;
int bitNumber = 0;
while (dif != 0 && ((dif & 1) == 0)
{
   dif = dif >> 1;
   ++bitNumber;
}
// bitNumber now contains the zero relative bit that is different.

答案 5 :(得分:1)

无法抗拒编写LINQish版本:

var firstBits = new BitArray(new byte[] { 3 });
var secondBits = new BitArray(new byte[] { 17 });

var lhs = firstBits.Cast<bool>().Select((b, i) => new { Bit = b, Index = i });
var rhs = secondBits.Cast<bool>().Select((b, i) => new { Bit = b, Index = i });

var differs = lhs.Zip(rhs, (l, r) => new { Left = l, Right = r })
                 .Where(zipped => zipped.Left.Bit != zipped.Right.Bit)
                 .Select(zipped => new { Index = zipped.Left.Index, LeftBit = zipped.Left.Bit, RightBit = zipped.Right.Bit });

foreach (var diff in differs)
{
    Console.WriteLine(String.Format("Differs in bit {0}:", diff.Index));
    Console.WriteLine(String.Format("   First is set to  {0}", diff.LeftBit));
    Console.WriteLine(String.Format("   Second is set to {0}", diff.RightBit));
}

更新

由于Zip运算符不是LINQ中的默认值,因此您可以从Eric out of his blog获取实现。

答案 6 :(得分:0)

其他人观察到,只有一个位的两个字节不同,XOR操作将返回一个字节,其中只有该位被置位。但是还没有人建议对我来说是明确的下一步是确定哪个位:

public static int WhichBitDiffers(byte a, byte b)
{
    var xor = a ^ b;

    switch(xor)
    {
        case 0x80:
            return 7;
        case 0x40:
            return 6;
        case 0x20:
            return 5;
        case 0x10:
            return 4;
        case 0x8:
            return 3;
        case 0x4:
            return 2;
        case 0x2:
            return 1;
        case 0x1:
            return 0;
        default:
            throw new ArgumentException(
                "Values do not differ in exactly one bit");
    }
}

我敢打赌,编译器/ JITter会使它成为一个很好的紧凑型跳转查找表,或类似的东西。