0%

关于干掉二进制连续末尾1or单个末尾1

蓝桥杯2016年 C/C++ A组 第五题

消除尾一

下面的代码把一个整数的二进制表示的最右边的连续的1全部变成0
如果最后一位是0,则原数字保持不变。

如果采用代码中的测试数据,应该输出:
00000000000000000000000001100111 00000000000000000000000001100000
00000000000000000000000000001100 00000000000000000000000000001100

请仔细阅读程序,填写划线部分缺少的代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>

void f(int x)
{
int i;
for(i=0; i<32; i++) printf("%d", (x>>(31-i))&1);
printf(" ");

```
x = _______________________;

for(i=0; i<32; i++) printf("%d", (x>>(31-i))&1);
printf("\n");
```

}

int main()
{
f(103);
f(12);
return 0;
}

去掉末尾的最后一个1:一个二进制 x=1000011010 去掉最后的一个1 可以先减去1 得到 1000011001

然后将两个二进制做与运算即 x&(x-1) 可以得到 1000011000 最后两个的互异 所以为0

去掉末尾连续的1:一个二进制 x=00000000000000000000000001100111 去掉末尾连续的1,可以先加上1 得到 00000000000000000000000001101000

然后再进行去除末尾1的处理,即可。代码:(x+1)&((x+1)-1)(x+1)&x

所以此题答案 (x+1)&x

整合代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//
// Created by ZhiNian on 2019/3/19.
//

#include <stdio.h>

void f(int x)
{
int i;
for(i=0; i<32; i++) printf("%d", (x>>(31-i))&1);
printf(" ");

// x = _______________________;
x = (x+1)&x;
for(i=0; i<32; i++) printf("%d", (x>>(31-i))&1);
printf("\n");
}

int main()
{
f(103);
f(12);
return 0;
}