我有两个字节,它们只有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
非常欢迎任何建议!!
谢谢,
埃里克
答案 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);
为了获得最高不同位的索引,如果有多个不同的话。
警告:为了正确起见,任何此类函数在尝试提供结果之前还应检查两个参数a
和b
是否实际不同。否则你将得到一个毫无意义的结果或一个彻头彻尾的例外。这适用于此处提供的所有解决方案,包括此解决方案。
答案 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会使它成为一个很好的紧凑型跳转查找表,或类似的东西。