基于long long的Bitmasking实现为何出现额外位错误?
位掩码集合实现的溢出问题排查
我在学习位掩码(Bitmasking)时,需要实现一个O(1)复杂度的集合数据结构,用于存储1<n<64的数字。但运行代码后,插入1、3、5、60并打印时,出现了28、33等额外数字;删除5后仍存在错误位,而非预期的1、3、60,请问这是为什么?
问题代码
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef vector<int> vi; class BitMask { public: ll n; BitMask() { //call the class as Bitmask varname; n = 0; } void insert(long long x) { n |= (1 << x); } void deleteItem(long long x) { if (n & (1 << x)) { n &= ~(1 << x); } } void print() { for (int i = 0; i < 64; i++) { if (n & (1 << i)) { cout << i << endl; } } } }; //implementation int main() { #ifndef ONLINE_JUDGE freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout); #endif BitMask obj1; //insertion obj1.insert(1); obj1.insert(5); obj1.insert(3); obj1.insert(60); //print obj1.print(); cout << endl; //deletion obj1.deleteItem(5); obj1.print(); cout << endl; return 0; }
问题原因
核心问题是整数溢出导致的未定义行为:
- 代码中
1 << x里的1是默认的32位int类型,而32位int的有效移位范围是0~31。当x≥32时,左移操作会触发溢出,生成的二进制值完全错误,直接污染了64位的位掩码变量n,导致出现28、33这类无关位被错误置1的情况。 - 删除操作同理,
1 << x溢出后无法正确定位目标位,要么删不掉指定值,要么误操作其他位。
修复方案
将移位操作的基数改为64位长整型,确保移位在合法范围内进行:
修改insert和deleteItem方法中的1 << x为1LL << x(1LL是64位长整型常量),这样左移60位不会溢出,能正确生成对应位的掩码。
修复后的关键代码:
void insert(long long x) { n |= (1LL << x); } void deleteItem(long long x) { if (n & (1LL << x)) { n &= ~(1LL << x); } }
内容的提问来源于stack exchange,提问作者Vivek Negi
相关产品推荐
相关产品推荐

