用C++写的,前两天看到一个博客上面写的idea,我感觉不错,于是实现了一下。
#include <iostream>
#include "CountOneNumbers.hpp"
int main(int argc, const char * argv[]) {
// insert code here...
int inputVariable = 1234;
CountOneNumbers::countOneNumbers0(inputVariable);
CountOneNumbers::printfBinary(inputVariable);
return 0;
}
#ifndef CountOneNumbers_hpp
#define CountOneNumbers_hpp
#include <stdio.h>
#include <iostream>
class CountOneNumbers {
public:
//打印该数的二进制有多少个1
static void countOneNumbers0(int someNumber);
//打印它的二进制形式
static void printfBinary(int someNumber);
};
#endif /* CountOneNumbers_hpp */
#include "CountOneNumbers.hpp"
//在这里要计算的是一个数的二进制表示中有多少个1.
//先分析一下思路,你要想知道一个数中有多少个1就应该把该数中的1一个一个的剥离出来。
//那么如何剥离出来呢?
//现在不知道,但是现在可以知道的是,剥离之前和剥离之后这个数的二进制表示的区别所在。
//现在假设被计算的数字是11001100
//被剥离以后的数字应该是11001000
//即,从右往左把遇到的第一个1抽出来。
//怎么样达到这一目的呢?
//须知2进制是比较特殊的进制,特殊点在于它只要发生进位或者借位就会不断影响前面的位。
//具体为如果发生借位,那么它会一直影响直到遇到左边第一个1,
//如果发生进位,那么它会一直影响直到遇到左边第一个0位置。
//其实这一点在其他进制里面也会遇到的,不过不像2进制这样敏感而已,比如说十进制数
//9999999,此时只要加1,它就会影响左边的数字直到遇到不是9的数字。
//那么回到如何剥离1这个话题来,从11001100到11001000正好是要把从右到左遇到的第一个1变成0的操作,
//于是借位操作能够满足这个要求,于是11001100减1得到11001011.
//再观察11001011和11001000的关系发现,
//只要把11001100和11001011进行异或即可得到11001000从而剥离出来一个1.
//那么不断剥离的极限是什么?那就是0没有了呗。
//那又代表什么?代表变成0了呗。
//在这里仅以正整数作为输入来统计数字中的1的个数。
void CountOneNumbers::countOneNumbers0(int someNumber) {
if (someNumber < 0) {
std::cout<<"输入不合法"<<std::endl;
return;
}
int oneCounter = 0;
while (someNumber > 0) {
someNumber = someNumber & someNumber - 1;
oneCounter++;
}
std::cout<<"1的个数为:"<<oneCounter<<std::endl;
}
//基于你可以用该方法来打印一个数字的二进制表示。
//这里还是假设输入的数字是自然数。
void CountOneNumbers::printfBinary(int someNumber) {
if (someNumber < 0) {
std::cout<<"输入不合法"<<std::endl;
return;
}
//因为上面的方法是从右到左,所以直接应用此法打印的是倒置的数列。
//所以要把它正过来才行。所以现在要做的是如何剥离最高位的1.
//首先获取int的位数,那么如何做到这一点呢?首先知道
//该数字所属类型,于是可知该类型所占字节数,进而可知该类型所占位数
//设置一个变量,这个变量的二进制形式是它只有一个1,并且这个1会从int类型的最高位
//移动到int类型的最低位。每次移动一下就和输入的数字相与只要不为0就说明遇到1了。
//否则跳过去。直到这个变量的幂指数变为负。或者把最大的2次方求出来然后不断除以2直到为0.
//不然老是求幂指数运算代价也很大。
//位移也可以实现但是高位补0还是补1并不统一,在类型正负变化的时候通用性不强。
//最高位有可能是符号位,对于有符号类型来说,所以还要考虑这一点。
//这个运算应该停留在应用层面而不是计算机底层的运算,因为每种语言或者计算机的底层实现有所差异
//而面向应用层的接口则可以保持不变。
//我所追求的就是通用。
bool canPrint = false;
std::cout<<someNumber<<"的二进制表示为:";
int powerSign = sizeof(someNumber) * 8 - 1;
//这里本来是用pow函数的,但是那需要用到math.h头文件
//感觉不太完美,于是采用移位操作。
unsigned int maxWeight = 1;
maxWeight = maxWeight << powerSign;
while (maxWeight > 0) {
if ((maxWeight & someNumber) > 0) {
std::cout<<"1";
canPrint = true;
} else {
if (canPrint)std::cout<<"0";
}
maxWeight /= 2;
}
std::cout<<std::endl;
}
输出如下
1的个数为:5
1234的二进制表示为:10011010010
Program ended with exit code: 0
网友评论