考试复习求助:无符号整数特定位模式查找函数实现问题
解决位模式匹配的误判问题
嘿,我太懂这种踩坑的感觉了!你用num & (pattern << i) == (pattern << i)的思路,其实只完成了一半的判断——它只能验证pattern里为1的位在num的对应位置也为1,但完全没管pattern里为0的位啊!举个例子:如果pattern是00000101(0x05),而num的对应位置是00001101,按你的条件算出来是相等的,但实际上中间多了个1,根本不符合模式,这就是误判的根源。
正确的思路:完全匹配位段
要准确检测pattern是否作为连续的位序列出现在num中,我们需要取出num中对应长度的位段,和pattern做完全相等的比较,而不是只检查1的位。具体步骤如下:
- 计算pattern的有效位长度和掩码:首先得知道pattern占了多少个有效位(从最低位到最高位的1之间的所有位),然后生成一个刚好覆盖这些位的掩码。比如0x05的二进制是
...00000101,最高位的1在第2位,所以有效位长度是3,掩码就是0x07(...00000111)。 - 遍历所有可能的起始位置:从num的第0位开始,依次把num右移i位,然后用掩码取出对应长度的位段,和pattern比较。如果相等,说明找到了匹配的序列。
完整代码实现
#include <stdbool.h> #include <stdint.h> bool find_sequence(unsigned int num, unsigned int pattern) { // 处理特殊情况:如果模式是0,可根据题目需求调整逻辑 if (pattern == 0) { return false; // 这里假设模式非0时才匹配,按需修改 } // 计算模式的有效位长度和对应的掩码 uint32_t temp = pattern; int bit_length = 0; while (temp != 0) { temp <<= 1; bit_length++; } unsigned int mask = (1U << bit_length) - 1; // 遍历所有可能的起始偏移量,避免移位越界 int max_offset = sizeof(unsigned int) * 8 - bit_length; for (int i = 0; i <= max_offset; i++) { // 取出num中从i位开始的bit_length位,和pattern比较 if (((num >> i) & mask) == pattern) { return true; } } return false; }
针对你的测试用例验证
你的测试值a = 82937转二进制是1010000111111001,模式b = 0x05是00000101。当i=14时,num >>14得到5(二进制00000101),和mask0x07相与后还是5,和pattern完全相等,所以函数会返回true,这是正确的匹配结果。
为什么原来的方法会误判?
假设num的某段位是00001101,pattern左移对应位置后是00000101,两者按位与的结果是00000101,等于pattern左移后的值,你的条件会认为匹配,但实际上num的对应位多了一个1,不符合模式。而新方法通过掩码取出完整的位段,确保每一位都和pattern完全一致,就不会出现这种误判了。
内容的提问来源于stack exchange,提问作者Darren
相关产品推荐
相关产品推荐

