我有一个32位整数,我通过将各个位映射到各种类型的数据来填充数据。
例如,一个部分用于氧气水平。它是0到128之间的值,所以我使用7位。
另一部分用于旋转对象。围绕三个轴x,y和z的旋转总是0度,90度,180度或270度。每个角度都用值0,1,2和3索引,所以我只需要6位。旋转存储为010101,围绕x,y和z旋转90度,或围绕x旋转180度旋转。
有些部分存储为整数值,例如氧气水平,但在需要使用时会转换为枚举。
每个部分在数据整数中彼此相邻布局,从右到左填充位。
Type : ... | Oxygen | Rotation |
--------------------------
Bits: ... | 0000000 | 000000 |
--------------------------
Position: ... | 19-25 | 26-31 |
--------------------------
我想比较两个整数,看看有什么变化。
当一个int的氧气水平为16,另一个为20的氧气水平时,差异为4个单位的增加。当一个旋转在所有轴上为0时,另一个在x周围为90时,差异是围绕x的旋转90度。
我在数据对象上有扩展方法,它允许我将氧气水平作为int值,并将旋转作为四元数。当在delta数据对象上使用它们时,我想获得氧气水平的值4,以及围绕x旋转90度的四元数。
获得两个整数值差异的最有效方法是什么?
我已经考虑过几种不同的方法来解决这个问题。
由于数据是整数,我试图简单地从另一个中减去一个。我从一个值为0的int开始,并将氧气水平的位设置为16.我创建了一个新的int,将其氧气水平设置为20,并从最后一个减去第一个,并且delta的氧气水平为4但是当我向整数添加旋转和其他数据时,减法后的结果改变了氧气水平和旋转。
我需要验证我的所有扩展方法是否按预期工作。所有单元测试都成功,但测试可能不够好。
另一种方法是使用各种按位运算符在整个整数中分别比较每个位。我使用了一个int,其旋转位设置为x周围90度(位01)。另一个int的x旋转设置为180度(位10)。我正在寻找的delta值是90度(位01),但是我找不到任何合适的运算符来产生该结果。
这个测试让我相信我不能分别比较比特。在旋转索引的情况下,我需要将一对位看作单个值。
我阅读了.net的BitArray文档,但无法立即看到使用它会产生任何影响。
比较每个比特部分将产生我正在寻找的结果。在计算差值之前,旋转位将转换为四元数,然后在将它们设置为数据整数之前转换回位。
这是我希望找到替代方法的方法。我不希望比较器知道数据的结构,我希望找到一个更有效的解决方案。
修改的
我现在看到,在阅读了评论并做了更多测试之后,我的情况更有利的是只得到一个部分的新值,而不是它们改变了多少。任何保持不变的部分都应归零。据我所见,我唯一的选择是分段比较数据。
再次修改
我不确定选择哪个答案是正确答案。我认为我的问题不够具体,对此我很抱歉。
@harold给出的方法在逐位比较时起作用,并且与数据结构无关。
@Pikoh的答案逐节比较,并且可以动态化,以便该方法不需要了解数据结构。
答案 0 :(得分:1)
我不确定您想要什么,但使用典型SWAR techniques计算所有字段的模块差异当然是可能的:
z = ((x | H) - (y &~H)) ^ ((x ^~y) & H)
这是SWAP减法的通用公式。对于2位字段H = 0xAAAAAAAA
。
由于只有两个位,并且SWAR通常以不同方式处理顶部位(以防止泄漏到下一个字段),所以这些位实际上是完全分开的。
根据新的要求,也没有必要对字段进行丑陋的拆分,例如:(未经测试)
m = x ^ y;
m = (m | (m >> 1)) & 0x55555555;
m *= 3;
z = y & m; // maybe
这里的想法是,如果字段已经改变,则xor将在字段中的某处产生1,然后将字段的所有位OR并将其置于字段的最低位,乘以3将其广播到所有位领域的。 &安培;使用新值在其他地方获取更改的字段和零,但这意味着您无法区分“已更改为0”和“未更改”。使用m
您仍可以区分它们。
答案 1 :(得分:0)
让我们看看这样的事情是否有助于你:
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
,这些似乎很容易比较。
希望这有帮助