钻头检查数字是否在特定范围内

时间:2011-01-01 10:14:16

标签: c++ c algorithm bit-manipulation

我在ICU库(International Components for Unicode)的"source\common\unicode\utf.h"文件中发现了一些有趣的内容。 bit twiddling用于检查数字是否在特定范围内。

// Is a code point in a range of U+d800..U+dbff?
#define U_IS_LEAD(c) (((c)&0xfffffc00)==0xd800)

我已经想出了幻数(0xfffffc00)来自:

MagicNumber = 0xffffffff - (HighBound - LowBound)

但是,我还发现该公式不适用于每个任意范围。这里有人知道这个公式在什么情况下起作用了吗?

是否还有另外一点需要检查数字是否在特定范围内?

3 个答案:

答案 0 :(得分:12)

要应用这些技巧,数字必须在其二进制表示中具有一些共同特征。

0xD800 == 0b1101_1000_0000_0000
0xDBFF == 0b1101_1011_1111_1111

这个测试真正做的是掩盖低十位。这通常写成

onlyHighBits = x & ~0x03FF

在此操作之后(“而不是”),onlyHighBits的低十位保证为零。这意味着,如果此数字等于现在的间隔的较低范围,则它已经在之前的间隔中的某个位置。

这个技巧适用于所有情况,其中间隔的下限和上限以二进制中的相同数字开始,并且在某些时候,下限仅有零,而上限只有1。在你的例子中,这是从右边的第十个位置。

答案 1 :(得分:4)

如果您没有2 ^ x边界类型,可能会使用以下技巧:

如果x >= 0x < N您可以通过以下方式检查:

  if Longword( x ) < Longword( N ) then ...

这是有效的,因为有符号数字中的负数对应于无符号数据类型中的最大数字。

您可以将此范围(当范围检查为DISABLED时)扩展为:

  if Longword( x - A ) < Longword ( ( B - A ) ) then ...

现在,您在SUB和CMP加上单个Jcc中都有两个测试(范围[ A, B >),假设(B - A)是预先计算的。

真正需要时,我只使用这些优化;例如,它们往往会降低您的代码的可读性,并且每次测试只会缩短几个时钟周期。

C语言读者注意:Longword是Delphi的无符号32位数据类型。

答案 2 :(得分:3)

只要您要查找的范围以2的幂的倍数(即,数字的二进制形式的低端的1位或更多位以0结尾)开始,该公式就会起作用。范围是2 ^ n-1(即低和高==低和低|高==高)。