我在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)
但是,我还发现该公式不适用于每个任意范围。这里有人知道这个公式在什么情况下起作用了吗?
是否还有另外一点需要检查数字是否在特定范围内?
答案 0 :(得分:12)
要应用这些技巧,数字必须在其二进制表示中具有一些共同特征。
0xD800 == 0b1101_1000_0000_0000
0xDBFF == 0b1101_1011_1111_1111
这个测试真正做的是掩盖低十位。这通常写成
onlyHighBits = x & ~0x03FF
在此操作之后(“而不是”),onlyHighBits
的低十位保证为零。这意味着,如果此数字等于现在的间隔的较低范围,则它已经在之前的间隔中的某个位置。
这个技巧适用于所有情况,其中间隔的下限和上限以二进制中的相同数字开始,并且在某些时候,下限仅有零,而上限只有1。在你的例子中,这是从右边的第十个位置。
答案 1 :(得分:4)
如果您没有2 ^ x边界类型,可能会使用以下技巧:
如果x >= 0
和x < 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(即低和高==低和低|高==高)。