方法1:因为没有异或^这样的直接运算符,计算同或可以转为string类型进行操作,再转为需要的类型
string a,b,res; cin >> a>>b; //0101 1001 这里需要控制一下输入的长度要一样,如果不同的话要自己实现短的前面补0 int length = a.length(); for (int i = 0; i <length; ++i) { if (a[i] == b[i]) res += '1'; else res += '0'; }
cout<<res; //因为是字符串所以最后需要根据需求转换为二进制,十进制
就是这么简单。。。愣是弄了三个小时,查遍了整个搜索引擎,基本都是按照运算法则:~(a^b)的思想出发进行实现的,导致我一直困在这个思想里面 唉。下面记录一下踩雷经过
1.首先想到代码
unsigned int a, b,c; a = 0B1010; b = 0B0000; c = ~(a^b);
很明显不会成功,因为计算机存储a,b是按4个字节存储的,前面会有很多0。所以最后结果是一个很大的整数。所以想:怎么才能只运算我需要的这几位,前面的0都忽略
搜遍了百度没找到答案,终于在stackoverflow找到了相同问题(https://stackoverflow.com/questions/49254856/perform-xnor-on-2-integers)
按照里面最后一个回答,使用bitset成功实现了基于~(a^b)思想的同或运算操作
方法二:bitset可以成功 但是有限制
unsigned int a, b,c; a = 0B1010; b = 0B0000; c = ~(a^b); cout <<bitset<4>(a)<<" "; cout << bitset<4>(b) << " "; cout << bitset<4>(c) << " ";
但很快问题又出现了,因为bitset初始化的长度必须是常量,在编译阶段就已经确定,但我要实现的是不定长度的二进制同或运算,没法提前精准知晓长度(即使定义很长的长度,bitset会在前面自动补0,这样就和没有用bitset一样了,没有意义)
自然的,我就想能不能像new定义数组一样,有动态定义bitset的方法,然后在stackoverflow中找到答案(https://stackoverflow.com/questions/3134718/define-bitset-size-at-initialization)
但我并没有去使用dynamic_bitset而是从里面一句话vector<bool>得到启发,为什么不用模拟方法而非要用算术运算呢,虽然运算符会更快,但我目前也没有那个必要啊。
最后,既然是模拟,数组并没有string类型的输入简单。所以最后采用string类型的两个变量模拟同或操作,这么简单的事愣是搞了这么久 kao。。。。。。。。。。。
最后是一题同或运算的笔试题:9/8 citrix笔试第三题
题目:给一个二进制的数(例如:1010)求0000最少需要翻转几次才能得到1010,翻转运算有特殊定义,当左边的1翻转为0时,其右边的所有字符都取反
例子:0000—》0001—》0010—》0101—》1010 需要4次 第一次翻转最后一个数,第二次翻转倒数第二个数,同时其后面的取反。第三次翻转第二个数。第四次翻转第一个数。完成
分析:应该是按照1010和0000不断取同或直到0,结果就是同或的次数 ,没法验证,应该是对的。
代码:
string xnor(string a, string str) { int len = str.length(); string res = ""; for (int i = 0; i < len; ++i) { if (a[i] == str[i]) res += '1'; else res += '0'; } return res; } int main() { string a; cin >> a; int res = 0; while (!a.empty()) //等价于不为0,因为0101这种前面的0会拿掉 { while (!a.empty()&&a[0] == '0') a.erase(a.begin()); //去掉首部多余的0 int len = a.length(); string str = ""; while (len--) str += '0'; //初始化str为00..0,0的个数由a的长度决定 a = xnor(a, str); res++; //同或一次则++ } cout << res-1; }