一行c表达式检测无符号整数是否是2的幂

Give a one-line C expression to test whether an unsigned int is a power of two.

用一行c表达式检测一个无符号整数是否是2的幂(2的幂是指2的正整数次幂,比如4,8,16)

答案:

((n&(n-1))==0)


答案的原理是这样的:

2的幂的2进制形式是1后面跟着很多个0,如

100

10000

1000000

只要看见这样的数,立刻可以判定它是。

n和n-1是形如这样的二进制数:

01000000

00111111

可以看到,对应的位总是0和1都出现,所以,n&(n-1)一定是0

有同学可能想到用异或,n^(n-1)一定是全1。这个仔细想来就会发现不行,前面的补充零会导致前面有一些0。

现在已经看到,对2的幂进行n&(n-1)一定会是0,那么别的数一定会是非0吗?

随便举例:10010

10010  //原数

10001  //原数减一

10000  //按位与之后的结果

可以看到,确实是非0。

那么为什么呢?

只要一个二进制数是2的幂,减1就会造成位数减少一位。其他 任何数,都不会造成这种位数减少的现象。即,只有形如1000...0的形式的数字才会导致位数减少一位。因此n的第一个1(高位1)才会被减走,变成0,按位与的时候才会是0,否则最高位必是1,含1会造成整个表达式非0。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现超过20位的无符号整数加法和乘法运算可以使用字符串来存储数字,然后模拟手算的方式进行运算。 以下是一份参考代码: ```c++ #include <iostream> #include <fstream> #include <string> #include <algorithm> using namespace std; string add(string a, string b) { reverse(a.begin(), a.end()); reverse(b.begin(), b.end()); int Alen = a.size(), Blen = b.size(); string res = ""; int carry = 0; for (int i = 0; i < max(Alen, Blen); i++) { int x = i < Alen ? a[i] - '0' : 0; int y = i < Blen ? b[i] - '0' : 0; int sum = x + y + carry; res += (char)(sum % 10 + '0'); carry = sum / 10; } if (carry > 0) { res += (char)(carry + '0'); } reverse(res.begin(), res.end()); return res; } string multiply(string a, string b) { reverse(a.begin(), a.end()); reverse(b.begin(), b.end()); int Alen = a.size(), Blen = b.size(); string res(Alen + Blen, '0'); for (int i = 0; i < Alen; i++) { int carry = 0; int x = a[i] - '0'; for (int j = 0; j < Blen; j++) { int y = b[j] - '0'; int product = x * y + carry + (res[i + j] - '0'); res[i + j] = (char)(product % 10 + '0'); carry = product / 10; } if (carry > 0) { res[i + Blen] += carry; } } reverse(res.begin(), res.end()); while (res.size() > 1 && res[0] == '0') { res.erase(0, 1); } return res; } int main() { ifstream fin("input.txt"); ofstream fout("output.txt"); string line; while (getline(fin, line)) { string a, b; char op; int i = 0; while (line[i] >= '0' && line[i] <= '9') { a += line[i]; i++; } op = line[i]; i++; while (i < line.size() && line[i] >= '0' && line[i] <= '9') { b += line[i]; i++; } if (op == '+') { fout << add(a, b) << endl; } else if (op == '*') { fout << multiply(a, b) << endl; } } fin.close(); fout.close(); return 0; } ``` 代码中使用了 `add` 函数和 `multiply` 函数来分别实现加法和乘法。这两个函数的实现都是通过将数字字符串反转后模拟手算的方式来实现的。在 `multiply` 函数中,还需要在每次计算乘积时,将当前位置的值加上之前已经计算出来的值,以支持多位数的乘法。 在主函数中,我们读取输入文件中的每一行,解析出其中的操作数和操作符,并调用相应的函数计算结果并输出到输出文件中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值