目录
4.十六进制转十进制(同样是字母的问题,同样使用分支结构解决)
一.进制问题
1.十进制转二进制
除2取余数得最低1位,然后把商继续除得第2位,直到商等于0(这里用循环实现)
#include <iostream>
using namespace std;
int main()
{
int num;
cin>>num;
int str[1000];
int i = 0;
while(num>0){
str[i++] = num%2;
num /= 2;
}
for(int j=i-1;j>=0;j--)
cout << str[j];
return 0;
}
这里需要注意的是要用int 整型数组来存储值,否则打印出来的不是数字字符了
用 ‘0’ + xxx 可以解决这个问题
#include <iostream>
using namespace std;
int main()
{
int num;
cin>>num;
char str[1000];
int i = 0;
while(num>0){
str[i++] = '0'+num%2;
num /= 2;
}
for(int j=i-1;j>=0;j--)
cout << str[j];
return 0;
}
同理:
十进制转八进制(把取余数的和除数都改成8就 欧克了)
#include <iostream>
using namespace std;
int main()
{
int num;
cin>>num;
char str[1000];
int i = 0;
while(num>0){
str[i++] = '0'+num%8;
num /= 8;
}
for(int j=i-1;j>=0;j--)
cout << str[j];
return 0;
}
什么九进制,七进制啥的都只用改变除数和取余的数即可!!!
2.十进制转十六进制(特殊的)
特殊在于:需要表示的还有字母,因此要用分支结构来分类讨论
#include <iostream>
using namespace std;
int main()
{
int num;
cin>>num;
char str[1000];
int i = 0;
int ch;
while(num>0){
ch = num%16;
if(ch>9){
str[i++] = 'a'+ch-10;
}
else str[i++] = '0'+ch;
num /= 16;
}
for(int j=i-1; j>=0; j--)
cout << str[j];
return 0;
}
同样适用于如十二进制,十八进制之类的转换
3.二进制转十进制
也就是每一位的 0 或 1 乘上 2的多少次方吧 (可以用pow()函数来计算)
也可以用一个 int term = 1 ; 每次都将ret 乘以一个2来进行更新!!!
值得注意的是:输入的二进制数可能太长不能用long long 保存
还是用char 数组更加保险,然后这里要记得强制类型转换(int),还有要从后往前计算!!!
#include <iostream>
using namespace std;
int main()
{
char num[100];
gets(num);
int term = 1;
int ret = 0;
int i = 0;
while(num[i]) i++;
while(i>0){
ret += ((int)num[--i]-48)*term;
term *= 2;
}
cout << ret;
return 0;
}
同理八进制转十进制:就是把term 的改变换成乘以8罢了
#include <iostream>
using namespace std;
int main()
{
char num[100];
gets(num);
int term = 1;
int ret = 0;
int i = 0;
while(num[i]) i++;
while(i>0){
ret += ((int)num[--i]-48)*term;
term *= 8;
}
cout << ret;
return 0;
}
4.十六进制转十进制(同样是字母的问题,同样使用分支结构解决)
#include <iostream>
using namespace std;
int main()
{
char num[100];
gets(num);
int term = 1;
int ret = 0;
int i = 0;
while(num[i]) i++;
int ch;
while(i>0){
ch = (int)num[--i];
if(ch>='a' && ch<='z')
ret += (ch-87)*term;
else if(ch>='A' && ch<='Z')
ret += (ch-55)*term;
else
ret += (ch-48)*term;
term *= 16;
}
cout << ret;
return 0;
}
这样子管他十二进制还是十八进制都可以用了(只用改变一下term 的迭代方程)
5.二进制转八进制
(一种思路是用十进制作为媒介,二到十到八,不过可能会有误差)
另外一种思路是:
从二进制到八进制就是每三个数字一组转化为一个八进制元素!!!
#include <iostream>
using namespace std;
int main()
{
char num[100];
int str[100] = {0};
gets(num);
int term = 1;
int div = 1;
int i = 0;
int j = 0;
int flag = 0;
while(num[i]) i++;
while(i>0){
if(flag==3){
str[j] /= div;
j++;
flag = 0;
div *= 8;
}
str[j] += term*((int)num[--i]-48);
term *= 2;
flag++;
}
if(flag!=3) str[j] /= div;
for(int k = j;k>=0;k--)
cout << str[k];
return 0;
}
这里有几个细节点:
str 用的是整型数组,并且一定要初始化为0
div 是除数,用于将每一项的数进行八进制化(其实就是利用了二转十再转八的思想)
每一项最后都要除以div,其中有可能首项由于没有凑满三项二进制数相加,因而没有进行相除操作,所以在跳出循环后,还要特地对首项进行一次操作
然后此处运用 flag 标志来实现三个为一组的运算!!!(里面的重置与迭代也很关键)
对于二进制转其他比如五进制,九进制啥的,还是用二转十,十进制再转换好了
优化:
#include <iostream>
using namespace std;
int main()
{
char num[100];
int str[100] = {0};
gets(num);
int term = 1;
int i = 0;
int j = 0;
int flag = 0;
while(num[i]) i++;
while(i>0){
if(flag==3){
j++;
flag = 0;
term = 1;
}
str[j] += term*((int)num[--i]-48);
term *= 2;
flag++;
}
for(int k = j;k>=0;k--)
cout << str[k];
return 0;
}
不用搞个什么div啊,只用把 term 重置就好了
6.二进制转十六进制
(二进制转十六进制,四个数字为一组,且要涉及数字和字母的转换)
用整型数组当作中间量,最后把大于9的元素转化为字母后再存到字符数组中
#include <iostream>
using namespace std;
int main()
{
string num;
cin>>num;
int n = num.size();
int* arr = new int[n/4+1]();
int term = 1;
int flag = 0;
int j = 0;
int div = 1;
for(int i=0;i<n;i++){
if(flag==4){
arr[j] /= div;
flag = 0;
j++;
div *= 16;
}
arr[j] += term*((int)num[i]-48);
flag++;
term *= 2;
}
if(flag!=4){
arr[j] /= div;
}
char* str = new char[j+2];
for(int i=0;i<=j;i++){
if(arr[i]<10)
str[j-i] = (char)(48+arr[i]);
else
str[j-i] = (char)(55+arr[i]);
}
str[j+1] = '\0';
cout<<str;
return 0;
}
值得注意的是:存入字符时要倒着存,从(j - i)开始,然后 j 的位置要取到,最后还要在末尾加上一个‘ \0’ 终止符!!!
优化:
#include <iostream>
using namespace std;
int main()
{
string num;
cin>>num;
int n = num.size();
int* arr = new int[n/4+1]();
int term = 1;
int flag = 0;
int j = 0;
for(int i=0;i<n;i++){
if(flag==4){
flag = 0;
j++;
term = 1;
}
arr[j] += term*((int)num[i]-48);
flag++;
term *= 2;
}
char* str = new char[j+2];
for(int i=0;i<=j;i++){
if(arr[i]<10)
str[j-i] = (char)(48+arr[i]);
else
str[j-i] = (char)(55+arr[i]);
}
str[j+1] = '\0';
cout<<str;
return 0;
}
7.八进制转二进制
(将每一个数字都拆成三个0与1的组合)
#include <iostream>
using namespace std;
int main()
{
string str;
cin>>str;
int n = str.size();
int j = 0;
int flag = 0;
int term = (int)str[j]-48;
int* arr = new int[n*3];
for(int i=0;i<n*3;i++){
if(flag==3){
term = (int)str[++j]-48;
flag = 0;
}
arr[i+2-flag*2] = term%2;
term /= 2;
flag++;
}
for(int i=0;i<3*n;i++)
cout<<arr[i];
return 0;
}
注意几个细节:
要用term把字符数组的值转换为数字在进行取模和除法运算
arr【i+2-2*flag】中的-2*flag 是为了实现在循环的小区间内的逆向存储
比如 6 ,计算出来顺序是011,而如果直接用arr【i】存储的话,则由于最后输出时是011,而不是正确的顺序110,所以要在小区间内逆向存储
【这里可以发散一下思维:如何实现每三个字符就逆向倒转一次】
然后这里flag要乘以2是为了抵消 i 的增加!!!【好好理解】
8.十六进制转二进制
(也就是将每一个数字或者字母拆成四个0与1的组合,用除法迭代即可)
(然后注意一下第七题里的事项就ok了)
#include <iostream>
using namespace std;
int fun(char ch)
{
return (ch>='0' && ch<='9')?((int)ch-48) :((int)ch-87);
}
int main()
{
string str;
cin>>str;
int n = str.size();
int j = 0;
int flag = 0;
int term = fun(str[j]); //这里规定输入的时小写字母
int* arr = new int[n*4];
for(int i=0;i<n*4;i++){
if(flag==4){
term = fun(str[++j]);
flag = 0;
}
arr[i+3-flag*2] = term%2;
term /= 2;
flag++;
}
for(int i=0;i<4*n;i++)
cout<<arr[i];
return 0;
}
9.十六进制转八进制
(4个一组的变成3个一组:十六转二再转八)
#include <iostream>
using namespace std;
int fun(char ch)
{
return (ch>='0' && ch<='9')?((int)ch-48) :((int)ch-87);
}
int main()
{
string str;
cin>>str;
int n = str.size();
int j = 0;
int flag = 0;
int term = fun(str[j]); //这里规定输入的时小写字母
int* arr = new int[n*4];
for(int i=0; i<n*4; i++){
if(flag==4){
term = fun(str[++j]);
flag = 0;
}
arr[i+3-flag*2] = term%2;
term /= 2;
flag++;
}
int m = 4*n/3+1;
int* s = new int[m]();
int i = 4*n;
int mid = 1;
int w = 0;
flag = 0;
while(i>0){
if(flag==3){
w++;
flag = 0;
mid = 1;
}
s[w] += mid*arr[--i];
mid *= 2;
flag++;
}
for(int k = w; k>=0; k--)
cout << s[k];
return 0;
}
10.八进制转十六进制
#include <iostream>
using namespace std;
int main()
{
string str;
cin>>str;
int n = str.size();
int j = 0;
int flag = 0;
int term = (int)str[0]-48; //这里规定输入的时小写字母
int* arr = new int[n*3];
for(int i=0; i<n*3; i++){
if(flag==3){
term = (int)str[++j]-48;
flag = 0;
}
arr[i+2-flag*2] = term%2;
term /= 2;
flag++;
}
int m = 3*n/4+1;
int* s = new int[m]();
int i = 3*n;
int mid = 1;
int w = 0;
flag = 0;
while(i>0){
if(flag==4){
w++;
flag = 0;
mid = 1;
}
s[w] += mid*arr[--i];
mid *= 2;
flag++;
}
for(int k = w; k>=0; k--){
if(s[k]<10)
cout << s[k];
else cout<< (char)(s[k]+55);
}
return 0;
}
11.最小的十六进制
问题描述
请找到一个大于 2022 的最小数,这个数转换成十六进制之后,所有的数位(不含前导 0)都为字母(A 到 F)。
请将这个数的十进制形式作为答案提交。
答案提交
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
#include <iostream>
using namespace std;
int main()
{
int temp;
int flag = 0;
for(int i = 2023;;i++){
temp = i;
for(int j = 0;j<3;j++){
if(temp%16 <= 9){
flag = 0;
break;
}
temp /= 16;
flag++;
}
if(flag == 3){
temp = i;
break;
}
}
cout<<temp;
return 0;
}
// Answer: 2730
优化:
#include <iostream>
using namespace std;
int main()
{
int temp;
int j;
for(int i = 2023;;i++){
temp = i;
for(j = 0;j<3;j++){
if(temp%16 <= 9){
break;
}
temp /= 16;
}
if(j == 3){
temp = i;
break;
}
}
cout<<temp;
return 0;
}
// Answer: 2730
12.二进制的位数
十进制整数 2 在十进制中是 1 位数,在二进制中对应 10 ,是 2 位数。
十进制整数 22 在十进制中是 2 位数,在二进制中对应 10110 ,是 5 位数。
请问十进制整数 2022 在二进制中是几位数?
tips:直接用十进制转二进制的算法,然后加入一个cnt变量计数即可
#include <iostream>
using namespace std;
int main()
{
int n;
cin>>n;
int cnt = 0;
while(n>0)
{
cnt++;
n /= 2;
}
cout<<cnt;
return 0;
}
// Answer: 11