进制转换:
(1) 十进制与二进制之间的转换
十进制转换为二进制,分为整数部分和小数部分
整数部分
方法:除2取余法,即每次将整数部分除以2,余数为该位权上的数,而商继续除以2,余数又为上一个位权上的数,这个步骤一直持续下去,直到商为0为止,最后读数时候,从最后一个余数读起,一直到最前面的一个余数。下面举例:
例:将十进制的168转换为二进制 得出结果 将十进制的168转换为二进制,(10101000)2
第一步,将168除以2,商84,余数为0。
第二步,将商84除以2,商42余数为0。
第三步,将商42除以2,商21余数为0。
第四步,将商21除以2,商10余数为1。
第五步,将商10除以2,商5余数为0。
第六步,将商5除以2,商2余数为1。
第七步,将商2除以2,商1余数为0。
第八步,将商1除以2,商0余数为1。
第九步,读数,因为最后一位是经过多次除以2才得到的,因此它是最高位,读数字从最后的余数向前读,即10101000
小数部分
方法:乘2取整法,即将小数部分乘以2,然后取整数部分,剩下的小数部分继续乘以2,然后取整数部分,剩下的小数部分又乘以2,一直取到小数部分为零为止。如果永远不能为零,就同十进制数的四舍五入一样,按照要求保留多少位小数时,就根据后面一位是0还是1,取舍,如果是零,舍掉,如果是1,向入一位。换句话说就是0舍1入。读数要从前面的整数读到后面的整数,下面举例:
例:将0.125换算为二进制 ,得出结果:将0.125换算为二进制(0.001)2
第一步,将0.125乘以2,得0.25,则整数部分为0,小数部分为0.25;
第二步, 将小数部分0.25乘以2,得0.5,则整数部分为0,小数部分为0.5;
第三步, 将小数部分0.5乘以2,得1.0,则整数部分为1,小数部分为0.0;
第四步,读数,从第一位读起,读到最后一位,即为0.001。
(2) 二/八/十六进制 转化为十进制
方法:按权相加法,即,将二/八/十六进制每位上的数乘以位权(2/8/16),然后相加之和即是十进制数。
(3) 二到八进制 或者 八进制转换为二进制
方法:
1. 二进制、八进制、十六进制相互转换:先转换成十进制再转换成其他进制;
2. 二进制、八进制、十六进制相互转换按照其对应关系进行转换(三位二进制数对应一位八进制数,四位二进制数对应一位十六进制数)。
位运算:
题目一:
在微软Excel中,用A表示第一列,B表示第二列,...,Z表示26,AA表示27,AB表示28.......;输入用字母表示列的编号,输出其是第几列?
分析: 这可以看做是一个26进制的数字转换为10进制的题目。类比二进制每个位用 0-1表示,此26进制的每个位用A~Z表示。
代码实现:
void chToNum(char *str)
{
char *tmp = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; //下标加一就是其数值
long long num = 0;
int len_tmp = strlen(tmp);
int len_str = strlen(str);
for (int i = 0; i < len_str; i++) //保证目标数据全部转换为大写
{
if (str[i] >= 'a' && str[i] <= 'z')
{
str[i] -= 32;
}
}
for (int i = 0; i < len_str; ++i)
{
for (int j = 0; j < len_tmp; ++j)
{
if (str[i] == tmp[j])
{
num = num * 26 + j + 1; //数据统计
}
}
}
printf("%d\n",num);
}
int main()
{
char str[27] = { '\0'};
printf("please input object num(input max is 26 numbers):\n");
scanf("%s", str);
chToNum(str);
}
题目二:
二进制中 1的个数。输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。例如9表示为二进制是 1001,则输入9时,函数输出为2,因为1001 中有两个 1。
代码实现1:
int NumberOf_1(int n)
{
int count = 0;
while (n)
{
if (n & 1)
count++;
n = n >> 1;
}
return count;
}
此实现有bug,如果n为负数,则n做右移时可能会导致n变成 0xFFFFFFFF 而陷入死循环。原则请参照右移时左边补位的规则。
代码实现2:
int NumberOf_1(int n) {
int count = 0;
unsigned int flag = 1;
while(flag)
{
if(n & flag)
count++;
flag = flag << 1;
}
return count;
}
此实现已经能满足要求了。
代码实现 3:
实现2中,当n为32位整数时,则需要循环32次;接下来介绍一种算法:整数中有几个 1 就循环几次。
分析:
如果一个不等于0,那么该整数的二进制表示中至少有一个 1;
(1). 假设这个数的最后一位为 1,那么减去 1,最后一位变成0,而其他位保持不变。
(2). 假设这个数的最后一位为 0,如果该整数的二进制表示中最右边的 1位于第m位,那么减去 1后,第m位由 1变为0,而第m位之后的0都变成1,整数中第m位前的位都不变。
(3). 总结前两点,当我们把一个整数减去 1,都是把最右边的 1变成0;如果它的右边还有0,则右边所有的0变成1,左边的位全保持不变
(4). 接下来我们把一个整数和它减去 1的结果做 与运算,相当于把它最右边的 1变成0,举例说明:当一个整数的二进制为1100时,减去 1的结果为 1011, 做 1100 & 1011 = 1000,所以当我们重复几次上述操作就有多少个 1 。
代码实现:
int NumberOf_1(int n) {
int count = 0;
while(n)
{
++count;
n = (n-1) & n;
}
return count;
}