目录
十进制转换成r进制
八、十六进制转二进制
二进制转八、十六进制
//将十进制数转化为二进制数并打印出其中1的个数
n = n & ( n - 1 ) 的奇妙运用
//获取一个二进制序列中的偶数位和奇数位,分别打印出二进制序列
//两个int(32位)整数m和n的二进制表达中,有多少个位(bit)不同
此篇博客旨在讲解C语言中进制转换问题,并且搭配一些小练习。
当然了,在开始做题之前,必备的知识是不可少的,赶快来看看进制之间是如何转换的吧~
十进制转换成r进制
十进制:D;二进制:B;八进制:O;十六进制:H
整数部分:除以r取余,即将十进制整数不断除以r取余数,直至商为0,余数从右向左排列,首次取得的余数在最右;
小数部分:乘以r取整,即将十进制小数不断乘以r取整数,直至小数部分为0或达到所要求的精度为止,所得整数从小数点自左向右排列,首次取得的整数在最左。
下面用图文来演示一下将十进制数123.456转化为二进制:
结果为1111011.011(B)小数点后几位数根据精度来定,不一定能够达到0,这里因为十进制取了小数点后三位,所以二进制也取后三位。
八、十六进制转二进制
一位八进制数对应三位二进制数;
一位十六进制数对应四位二进制数。
简单来说,就是将八进制和十六进制数的每一位拆开来看,分别用二进制表示即可。
下面我们同样用图文来演示一下:
二进制转八、十六进制
这就相当于上面转换的逆运算,道理是一样的哈~
整数部分:从右向左按三(四)位进行分组,不足补零;
小数部分:从左向右按三(四)位进行分组,不足补零。
注意方向(相当于都从小数点出发),可不要记错了哦!
//将十进制数转化为二进制数并打印出其中1的个数
法一:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{printf("请输入一个十进制数:");int n = 0;int length = 0;//用length来装二进制数的个数int arr[20];//定义一个数组来装余二得到的余数scanf("%d", &n);while ( n/2 ){arr[length] = n % 2;//存入数组中的是倒序的二进制序列length++;n = n / 2;}arr[length] = n % 2;//存储最后一个余数(当n/2==0时跳出循环,此时最后一位余数还未存储)int i = 0; //此时length是最后一个数的下标printf("转为二进制为:");for (i = length ; i >= 0; i--)//将余数从下往上输出{printf("%d", arr[i]);}printf("\n");int count = 0;for (i = 0; i <= length; i++)//注意length是下标,所以要 <={if (arr[i] == 1){count++;}}printf("其中有%d个数字1", count);return 0;
}
法二:如果只要统计二进制中1的个数,可以简洁地这样写:
法三:来个高级点的,运用我们学过的操作符 & 和 >> 也可完成 :
当然是有点小绕,不过问题不大。
int main()
{printf("请输入一个数:");int n = 0;scanf("%d", &n);//假设n为8——100int i = 0;int count = 0;for (i = 0; i < 32; i++){if ((n >> i) & 1)//将二进制中的每一位逐个与1按位与&,这一位是1得到1,这一位是0得到0{ // n>>i --- 100 --> 010 --> 001 count++; // 1 --- 001 --> 001 --> 001} // & --- 000 --> 000 --> 001} //所以8的二进制只有一个1printf("%d\n", count);return 0;
}
n = n & ( n - 1 ) 的奇妙运用
法四:最玄幻的操作了,效率也是最高的,如果你掌握了,可以向其他人装B了(bushi。
这也是谷歌面试题中的思路,还是很重要滴~
重点:n = n & ( n - 1 )
int main()
{printf("请输入一个数:");int n = 0;int count = 0;scanf("%d", &n);while (n){n = n & (n - 1);count++;}printf("%d", count);return 0;
}
结果也照样能跑起来哦。
再来看看这个公式还有哪些应用,如果让你写一个程序判断一个数是不是2的k次方,你会怎么做?是哼哧哼哧写上几十行代码,然后再忙不迭地改错?No no no,用这个公式几行代码就能搞定:
int main()
{printf("请输入一个数:");int n = 0;scanf("%d", &n);if ((n & (n - 1)) == 0)//注意这里的关系运算符 == 的优先级高于位运算符 & ,所以要加( ),否则结果全是No{printf("Yes\n");}else{printf("No\n");}return 0;
}
//获取一个二进制序列中的偶数位和奇数位,分别打印出二进制序列
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>int main()
{printf("请输入一个十进制数:");int n = 0;int length = 0;int arr[20];scanf("%d", &n);while (n / 2){arr[length] = n % 2;length++;n = n / 2;}arr[length] = n % 2;int i = 0;printf("其二进制为:");for (i = length; i >= 0; i--){printf("%d", arr[i]);//一直到这里都与上面一题完全相同}printf("\n");//换行printf("奇数序列为:");for (i = length; i >= 0; i--){if (i % 2 == 0)//打印奇数序列{printf("%d", arr[i]);}}printf("\n");//换行printf("偶数序列为:");for (i = length; i >= 0; i--){if (i % 2 == 1)//打印偶数序列{printf("%d", arr[i]);}}printf("\n");return 0;
}
我们同样可以用上一题的&与>>来实现,代码会简洁不少:
int main()
{printf("请输入一个数:");int n = 0;scanf("%d", &n);int i = 0;printf("偶数位:");for (i = 30; i >= 0; i -= 2){printf("%d ", (n >> i) & 1);}printf("\n");printf("奇数位:");for (i = 31; i >= 0; i -= 2){printf("%d ", (n >> i) & 1);}return 0;
}
//两个int(32位)整数m和n的二进制表达中,有多少个位(bit)不同
emmm……这可咋整??嘿嘿,如果能巧妙运用按位异或^这个操作符,题目就简单了~
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{int num1 = 0;int num2 = 0;int m = 0;int length = 0;//作为数组下标int arr[20];//定义一个数组放m的二进制序列printf("请输入两个数:");scanf("%d %d", &num1, &num2);m = num1 ^ num2;//按位异或后0与0为0,1与1为1,只有0与1时才为1while (m / 2) //相当于bit位不同时为1(神奇~){arr[length] = m % 2;//虽然这里存放的二进制位全是反向的,但不影响计数就行m = m / 2;//只有这个地方改变了m的值length++;}arr[length] = m % 2;//放入最后一个二进制数int i = 0;int count = 0;//作为计数器,记录有几个1for (i = 0; i <= length; i++)//{if (arr[i] == 1){count++;}}printf("二进制码不同位的个数为:%d\n", count);return 0;
}
That's all ~ 创作不易,如果内容对你们有帮助,麻烦一键三连哦!如果发现什么Bug,也欢迎评论区里指正哦!菜菜先在这里谢过大家啦~