回应上篇文章结尾的问题,解题前让我先带大家了解一下<<、>>左右移操作符,位移操作符又分为逻辑位移和算术位移,在我们学习用二进制表示一个数时,我们应该知道整数数据是以补码的形式存放在内存中的,而计算机在计算后呈现给用户看的是原码形式,因为正数的原码、反码、补码相同,所以有人对正数在内存中的储存理解有一些误差。
什么是逻辑位移和算术位移?
在我们进行位移操作的时候,比如int类型的元素左移一位,那么表示这个整数元素的二进制数就会左边多出一位数,右边少一位数,此时左边多出的数会被电脑丢掉,我们称这种情况为数据溢出。而在右边少的那一位上补0,这时逻辑位移和算术位移等效。例如:数字63<<1,0000 0000 0000 0000 0000 0000 0011 1111变成0000 0000 0000 0000 0000 0000 0111 1110 。但如果是向右移一位,电脑执行逻辑右移的时候:最右边的数字溢出被丢掉,最左边补0;电脑执行算术逻辑的时候:正数补0,负数补1(补的是符号位)。
那么既然我们知道了位移操作的逻辑,该如何去用它实现这个算法?
上一章我们讲到过&(按二进制位与)的作用是比较两个二进制位数,只有都为1才为1。那我们让一个数位与上1,是不是只用比较那个数二进制的最后一位和1?
#include<stdio.h>
int main() {
int a = 0;
scanf_s("%d", &a); //输入a的值
int count = 0;
for (int i = 0; i < 32; i++){
if (a & 1 == 1)
count += 1; //a的二进制位向右移一位
a = a >> 1;
}
printf("%d", count);
return 0;
}
输入数在整型范围内时,以上代码输出都是ok的
上篇原本的代码输出不了负数,所以改了一下,敬请各位多多包涵!