C# 对整数的位求差

C# 对整数的位求差,c#,integer,bit-manipulation,C#,Integer,Bit Manipulation,我有一个32位整数,通过将各个位映射到各种类型的数据来填充数据 例如,一个部分用于氧气水平。它是一个从0到128的值,所以我使用7位 另一部分用于对象的旋转。围绕三个轴x、y和z旋转始终为0、90、180或270度。每个角度的索引值为0、1、2和3,所以我只需要6位。旋转存储为010101,用于绕x、y和z旋转90度,或100000,用于绕x旋转180度 有些部分存储为整数值,如氧气水平,但在需要时转换为枚举 每个部分在数据整数中彼此相邻,从右到左填充位 Type : ... | Oxyg

我有一个32位整数,通过将各个位映射到各种类型的数据来填充数据

例如,一个部分用于氧气水平。它是一个从0到128的值,所以我使用7位

另一部分用于对象的旋转。围绕三个轴x、y和z旋转始终为0、90、180或270度。每个角度的索引值为0、1、2和3,所以我只需要6位。旋转存储为010101,用于绕x、y和z旋转90度,或100000,用于绕x旋转180度

有些部分存储为整数值,如氧气水平,但在需要时转换为枚举

每个部分在数据整数中彼此相邻,从右到左填充位

Type :    ... | Oxygen  | Rotation |
          --------------------------
Bits:     ... | 0000000 | 000000   |
          --------------------------
Position: ... | 19-25   | 26-31    |
          --------------------------
问题 我想比较两个整数,看看有什么变化

当一个int的氧含量为16,另一个int的氧含量为20时,差值增加4个单位。当一个旋转在所有轴上为0,另一个旋转在x轴上为90时,差值为围绕x轴旋转90度

我在数据对象上有扩展方法,允许我将氧气水平作为int值,将旋转作为四元数。当在delta数据对象上使用这些值时,我想得到氧水平的值4,以及围绕x旋转90度的四元数

问题: 获取两个整数值之差的最有效方法是什么

可能的办法 我考虑过几种不同的方法来解决这个问题

整数比较 因为数据是一个整数,我试着简单地从一个减去另一个。我从一个值为0的int开始,并将氧气水平的位设置为16。我创建了一个新的整数,将它的氧含量设置为20,然后从最后一个整数中减去第一个整数,δ的氧含量为4。但当我把旋转和其他数据加到整数上时,减法后的结果改变了产生的氧气水平和旋转

我需要验证我的所有扩展方法是否按预期工作。所有单元测试都成功,但测试可能不够好

逐位比较 另一种方法是使用各种逐位运算符在整个整数中分别比较每一位。我使用了一个int,旋转位设置为x周围90度(位01)。另一个int将x旋转设置为180度(位10)。我要寻找的增量值是90度(位01),但我找不到任何合适的运算符来生成该结果

这个测试让我相信我不能单独比较位。在旋转索引的情况下,我需要将一对位视为单个值

位数组 我阅读了.net的BitArray文档,但无法立即看出使用它会有什么不同

比较每个部分 比较每个位部分将产生我想要的结果。在计算差值之前,旋转位将转换为四元数,然后在数据整数中设置它们之前,将其转换回位

这是我希望找到的替代方法。我不想让比较器知道数据的结构,我希望找到一个更有效的解决方案

编辑

在阅读了评论并做了更多的测试之后,我现在明白了,对于我的案例来说,只获取一个bit部分的新值,而不是它们发生了多大的变化,将更加有益。任何保持不变的部分都应归零。就我所见,我唯一的选择是分段比较数据

重新编辑

我不确定选择哪个答案是正确的。我认为我的问题不够具体,对此我很抱歉

@harold给出的方法在逐位比较时有效,并且与数据结构无关


@Pikoh的答案逐节进行比较,并且可以使其成为动态的,这样该方法就不需要了解数据结构。

让我们看看这样做是否有助于您:

int data1 = Convert.ToInt32("00000000000000000000000000011100", 2); //sample data
int data2 = Convert.ToInt32("00000000000000000000000000101000", 2);
int xrotationposition = 26; //start positions of data
int yrotationposition = 28;

string xrotationmask = new string('0', xrotationposition) + "11" + 
                   new string('0',30 - xrotationposition); //mask to extract the data
string yrotationmask = new string('0', yrotationposition) + "11" + 
                   new string('0', 30 - yrotationposition);

int xrotation1 = data1 & Convert.ToInt32(xrotationmask, 2); //bit AND
int xrotation2 = data2 & Convert.ToInt32(xrotationmask, 2);

int yrotation1 = data1 & Convert.ToInt32(yrotationmask, 2);
int yrotation2 = data2 & Convert.ToInt32(yrotationmask, 2);

xrotation1 = (xrotation1 >> 30 - xrotationposition); //shift the bits 
                                                     to the lowest part of byte
xrotation2 = (xrotation2 >> 30 - xrotationposition);

yrotation1 = (yrotation1 >> 30 - yrotationposition);
yrotation2 = (yrotation2 >> 30 - yrotationposition);
在执行结束时,您将得到
xrotation1=1
xrotation2=2
yrotation1=3
yrotation2=2
,这些值似乎很容易比较


希望这对您有所帮助

我不确定您想要什么,但可以使用典型的:

这是交换减法的一般公式。对于2位字段,
H=0xaaaaaa

由于只有两个位,而SWAR通常以不同的方式处理顶部位(以防止泄漏到下一个字段),因此这些位实际上是完全分离的


根据新的需求,也不需要对字段进行难看的拆分,例如:(未测试)


这里的想法是,异或将在某个字段中的某个地方产生1,如果它已更改,那么或字段的所有位,并将其放入字段的最低位,乘以3将其广播到字段的所有位使用新值可以在其他地方获得更改的字段和零,但这意味着您无法区分“更改为0”和“未更改”。使用
m
你仍然可以区分它们。

如果减法不是你想要的,那么“区别”是什么?检测两个整数是不同的并不重要。如果您想要“这个”差异,您需要首先定义这个操作。仅仅说明如何布局数据是不够的。(听起来你想让不同的部分有多个“差异”。“差异”还不足以告诉我们你想要什么。您需要告诉我们这种差异比较的预期输出。这一点在你问题的这一部分也很明显:“没有产生我想要的结果”。你没有告诉我们你在找什么,所以我们帮不了你。在我看来,第二种选择是最简单的。库伊
z = ((x | H) - (y &~H)) ^ ((x ^~y) & H)
m = x ^ y;
m = (m | (m >> 1)) & 0x55555555;
m *= 3;
z = y & m; // maybe