如何仅使用数学从16位寄存器中提取特定位?

时间:2015-01-13 18:27:49

标签: word bit

我有一个16位WORD,我想读取特定位或几位的状态。

我尝试过一种方法,将单词除以我想要的位,将结果转换为两个值 - 一个整数和一个实数,并比较两者。如果它们不相等,则它等于假。这似乎只有在我寻找一个字的最后一个“TRUE”位时才有效。如果有任何连续的TRUE位,则失败。也许我只是没有做对。我没有能力使用代码,只有基本的数学,布尔运算和类型转换。有任何想法吗?我希望这不是一个愚蠢的问题,但我有一种感觉。

例如:

WORD 0010000100100100 = 9348

我想知道第2位的值。如何从9348确定它?

enter image description here

6 个答案:

答案 0 :(得分:1)

有很多方法,具体取决于您可以使用的操作。看起来你没什么可供选择的。但这应该工作,只使用整数除法和乘法,并测试相等性。 (伪码):

x = 9348 (binary 0010000100100100, bit 0 = 0, bit 1 = 0, bit 2 = 1, ...)
x = x / 4 (now x is 1000010010010000
y = (x / 2) * 2 (y is 0000010010010000)
if (x == y) {
    (bit 2 must have been 0)
} else {
    (bit 2 must have been 1)
}

每次除以2时,将位移到左侧的一个位置(以大端表示)。每次乘以2,都会将位移到右边的位置。奇数将在最不重要的位置有1。即使数字在最不重要的位置也会有0。如果在整数数学中将奇数除以2,然后乘以2,则会丢失奇数位(如果有的话)。所以上面的想法是首先将你想知道的位移到最不重要的位置。然后,除以2然后乘以2。如果结果与之前的结果相同,则您关注的位中必定有0。如果结果与之前的结果不一样,那么你所关心的位一定是1。

解释了这个想法后,我们可以简化为

((x / 8) * 2) <> (x / 4)

如果该位置位则将解析为true,如果未设置该位则将为false。

答案 1 :(得分:1)

和带掩码的单词[1]。

在你的例子中,你对第二位感兴趣,所以掩码(二进制)是 00000010.(十进制为2。)

在二进制文件中,您的单词9348是0010010010000100 [2]

    0010010010000100 (your word)
AND 0000000000000010 (mask)
    ----------------
    0000000000000000 (result of ANDing your word and the mask)

因为该值等于零,所以不设置该位。如果它与零不同,则设置该位。

此技术适用于一次提取一位。但是,如果您对提取多个位感兴趣,可以使用不同的掩码重复使用它。

[1]有关屏蔽技术的更多信息,请参阅http://en.wikipedia.org/wiki/Mask_(computing)

[2]见http://www.binaryhexconverter.com/decimal-to-binary-converter

答案 2 :(得分:0)

第n位等于除以2 ^ n mod 2

的字

我认为您必须测试每个位,0到15(包括0和15)。

答案 3 :(得分:0)

您可以尝试9348 AND 4(相当于1&lt;&lt;&lt; 2 - 您想要的位的索引)

9348 AND 4 
如果设置了位,

应该给4,否则给0。

答案 4 :(得分:0)

以下是我提出的建议:3个解决方案。一个是上面提到的Hatchet,他的回答帮助我真正了解了它的工作原理,这对我来说至关重要!如果我的系统支持按位运算符,那么建议的AND屏蔽解决方案可以工作,但显然不是。

原创技术:

( ( ( INT ( TAG / BIT ) ) / 2 ) - ( INT ( ( INT ( TAG / BIT ) ) / 2 ) ) <> 0 )

说明: 在等式的第一部分中,对TAG / BIT执行整数除法,然后将REAL除以2.在第二部分中,执行整数除法TAG / BIT,然后再将整数除以2.这两个结果之间的差异是与0比较。如果差值不为0,则公式解析为TRUE,这意味着指定的位也为TRUE。

例如:9348/4 = 2337 w /整数除法。然后2337/2 = 1168.5 w / REAL除以1168 w /整数除法。 1168.5-1168&lt;&gt; 0,所以结果为TRUE。

我修改过的技术:

( INT ( TAG / BIT ) / 2 ) <> ( INT ( INT ( TAG / BIT ) / 2 ) ) 

说明: 实际上与上面相同,但我只是将两个结果本身进行比较,而不是减去两个结果并将它们与0进行比较。如果它们不相等,则公式解析为TRUE,这意味着指定的位也为TRUE。

例如:9348/4 = 2337 w /整数除法。然后2337/2 = 1168.5 w / REAL除以1168 w /整数除法。 1168.5&lt;&gt; 1168,结果为TRUE。

Hatchet的技术适用于我的系统:

( INT ( TAG / BIT )) <> ( INT ( INT ( TAG / BIT ) / 2 ) * 2 )

说明: 在等式的第一部分中,在TAG / BIT上执行整数除法。在第二部分中,整数除法执行TAG / BIT,然后整数除以2,然后乘以2.比较两个结果。如果它们不相等,则公式解析为TRUE,这意味着指定的位也为TRUE。

例如:9348/4 = 2337.然后2337/2 = 1168 w /整数除法。那么1168x2 = 2336。 2337&lt;&gt; 2336所以结果为TRUE。正如Hatchet所说,这种方法'会丢掉奇数位'。


注意 - 9348/4 = 2337 w / REAL和整数除法,但重要的是公式的这些部分使用整数除法而不是REAL除法(12164/32 = 380 w /整数除法和380.125 w / REAL师)

我觉得重要的是要注意以后的任何读者上面的等式中的BIT值不是位数,而是如果所需位置中的位是二进制中唯一的TRUE位,则得到的十进制的实际值string(bit 2 = 4(2 ^ 2),bit 6 = 64(2 ^ 6))

对于某些人来说,这种解释可能有点过于简单,但对其他人来说可能是完美的:)

如有必要,请随时评论/批评/纠正我!

答案 5 :(得分:0)

我只需要将整数状态代码解析为位状态,以便与某些硬件接口。这是一个适合我的方法:

private bool resolveBitState(int value, int bitNumber)
{
    return (value & (1 << (bitNumber - 1))) != 0;
}

我喜欢它,因为它是非迭代的,不需要强制转换操作,并且本质上直接转换为Shift,And和Comparison等机器代码操作,这可能意味着它真的是最优的。

为了更详细地解释,我使用AND运算将按位值与我感兴趣的位(值和掩码)的掩码进行比较。如果按位AND运算结果为零,则不设置该位(返回false)。如果AND运算结果不为零,则设置该位(返回true)。 AND运算的结果是零或位的值(1,2,4,8,16,32 ......)。因此,比较AND运算结果和0的布尔值评估。通过取数字1并将其向左移位(逐位),通过适当数量的二进制位(1

我很惊讶没有人评价我的解决方案。它认为它最合乎逻辑,最简洁......并且有效。