【发布时间】:2016-05-04 08:38:07
【问题描述】:
我有一个 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,另一个为20时,相差增加4个单位。当一个旋转在所有轴上为 0,另一个是围绕 x 旋转 90 时,差异是围绕 x 旋转 90 度。
我在数据对象上有扩展方法,允许我将氧气水平作为 int 值,将旋转作为四元数。当在 delta 数据对象上使用这些时,我想获得氧气水平的值 4,以及围绕 x 旋转 90 度的四元数。
问题
获取两个整数值差的最有效方法是什么?
可能的方法
我想了几种不同的方法来解决这个问题。
整数比较
由于数据是一个整数,我试图简单地从另一个中减去一个。我从一个值为 0 的 int 开始,并将氧水平的位设置为 16。我创建了一个新的 int,将其氧水平设置为 20,然后从最后一个减去第一个,增量的氧水平为 4 . 但是当我向整数添加旋转和其他数据时,减法后的结果改变了产生的氧气水平和旋转。
我需要验证我的所有扩展方法都按预期工作。所有单元测试都成功,但测试可能不够好。
按位比较
另一种方法是使用各种位运算符分别比较整个整数中的每个位。我使用了一个 int,其旋转位设置为围绕 x 90 度(位 01)。另一个 int 将 x 旋转设置为 180 度(位 10)。我正在寻找的 delta 值为 90 度(位 01),但我找不到任何合适的运算符来产生该结果。
这个测试让我相信我不能单独比较位。在旋转索引的情况下,我需要将一对位视为单个值。
位数组
我阅读了 .net 的 BitArray 的文档,但无法立即看出使用它会有什么不同。
比较每个部分
比较每个位部分会产生我正在寻找的结果。在计算差值之前,旋转位将转换为四元数,然后在将它们设置为数据整数之前转换回位。
这是我希望找到替代方法的方法。我不想让比较器知道数据的结构,我希望找到更有效的解决方案。
编辑
我现在看到,在阅读了 cmets 并进行了更多测试之后,对于我的案例来说,仅获得位部分的新值而不是它们改变了多少对我来说更有利。任何保持不变的部分都应归零。据我所知,我唯一的选择是分段比较数据。
再次编辑
我不确定选择哪个答案作为正确答案。我认为我的问题不够具体,对此我深表歉意。
@harold 给出的方法在逐位比较时有效,并且与数据结构无关。
@Pikoh 的回答逐节比较,并且可以动态化,这样该方法就不需要了解数据结构。
【问题讨论】:
-
如果减法不是您想要的,“区别”是什么?检测两个整数 是 不同是微不足道的。如果您想要“差异”,则需要先定义此操作。仅仅说明如何布置数据是不够的。 (听起来您希望不同部分有多个“差异”。)
-
“差异”不足以告诉我们您想要什么。您需要告诉我们这种差异比较的预期输出。这在您问题的这一部分中也很明显:“没有产生我想要的结果”。您还没有告诉我们您在寻找什么,所以我们无法帮助您。
-
听起来第二个选项是最直接的。您可以发布您为此尝试过的代码吗?
-
对于您的旋转,您可能需要考虑不同的编码 - 0° -> 00、90° -> 01、180° -> 11 和 270° -> 10。这样,只有相隔 90° 的角度之间的一个位差。
-
如果您只想要新值,您可以简单地将旧值与新值异或,然后将结果与新值异或。所以只有改变的位在结果中,其他位全部清零。
标签: c# integer bit-manipulation