进制转换(C++)

题目链接

进制转换

题目描述与示例

给定一个十进制数M,以及需要转换的进制数N。将十进制数M转化为N进制数

输入描述

输入为一行,M(32位整数)、N(2 ≤ N ≤ 16),以空格隔开。

输出描述

为每个测试实例输出转换后的数,每个输出占一行。如果N大于9,则对应的数字规则参考16进制(比如,10用A表示,等等)

示例

输入:

7 2

输出:

111

解题思路

题目分析

这个题目还是比较容易理解的,就是把十进制数字M转化为N进制,超过10的部分按十六进制格式输出

个人思路

  1. 先写普遍情况即N<9时,因为这个时候全是数字
  2. 辗转相除获取余数存放到vector里面
  3. 逆置vector输出即可
  4. 对大于10的数字一一替换成ABCDE

为了避免有些小伙伴不知道辗转相除具体是怎么实现的,这里我直接从网上抠了个图过来描述一下我的理解:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nSX5DjTV-1653552587404)(C:\Users\lwz\AppData\Roaming\Typora\typora-user-images\image-20220522150904592.png)]

29转化为2进制,按上述我的思路计算完了之后vector存放的数据为10111,所以需要逆置成11101才是正确的输出形式,有关辗转相除的进制转化原理,在查看了各路大神的解释后我的理解大致如下:

(本来我以为我可以直接描述的,好像不太会措辞了,所以还是结合实例吧,这里还是29转2进制)

  1. 29%2=1
  2. [(29-1*2^0)%2]%2=0
  3. {[(29 - 1* 2^0) % 2 - 0*2^1] % 2 }%2= 1
  4. …………

大致思路其实就是除以进制,得到低位,然后减去低位,继续除以进制得到高位,只不过运算更为方便简洁,每一步余数都是计算得出的数位上的数字,还省下了减去低位的运算过程,不得不说发明这个算法的人的确很厉害。比如上述的第一步求出的就是29对应二进制位的第一位数字,以此类推。

代码展示

#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;

int main()
{
    int M,N;
    cin>>M>>N;
    vector<string> A;
    while(M%N !=M )
    {
        int b=M%N;//余
        if(b==10)
            A.push_back("A");
        else if(b==11)
            A.push_back("B");
        else if(b==12)
            A.push_back("C");
        else if(b==13)
            A.push_back("D");
        else if(b==14)
            A.push_back("E");
        else if(b==15)
            A.push_back("F");
        else
            A.push_back(to_string(b));
        M=M/N;
    }
    //完了对M还需要判断
    if(M==10)
        A.push_back("A");
    else if(M==11)
        A.push_back("B");
    else if(M==12)
        A.push_back("C");
    else if(M==13)
        A.push_back("D");
    else if(M==14)
        A.push_back("E");
    else if(M==15)
        A.push_back("F");
    else
        A.push_back(to_string(M));
    reverse(A.begin(),A.end());
    for(auto e:A)
    {
        cout<<e;
    }
    return 0;
}

但是很可惜上述代码跑不过,会有部分测试用例跑不过,因为我在做的时候看不到他的测试用例只知道跑不过所以当时也没有发现问题所在,知道看题解的时候才知道是自己忽略的M可能是一个负数的情况。

当M是一个负数的话那么vector里面的数字都是负数,这样输出出来的数据是不符合规则的,所以给出了下列解决方案:

  1. 定义一个bool类型的flag=false
  2. 如果M为负数,就让M=-M,flag=true
  3. 在最后输出vector时判断
  4. 如果flag=true就输出一个’-'号即可

具体解决方案已经给出,代码的话感兴趣的可以自己添上(不过大概率没人会像我这么做)

题解

关于题解大致思路都是一样的,只是部分细节处理上稍有不同,这里就直接给出我觉得最简洁的,先上代码:

#include <iostream>
using namespace std;
int main(){
	string s="",table="0123456789ABCDEF";
	int m,n;
	cin>>m>>n;
	while(m){
		if(m<0){
			m=-m;
			cout<<"-";
		}
		s=table[m%n]+s;
		m/=n;
	}
	cout<<s<<endl;
	return 0;
}

这个原理实际上也是辗转相除的思想,就不多说,这个精髓就在于有一个table的串把0-15的数字以及对应字母都保存了下来,取出余数后可以直接通过下标访问到table串里对应的元素,就不需要我那样傻傻的转化成字母;再者我觉得比较新颖的地方在于在拼接字符串的时候他用的是s=table[m%n]+s,而不是s+=table[m%n],一般对我来讲,因为用习惯了后面的那种拼接方式然后逆置整个串,就忽略了这样的拼接,这样的拼接就直接少了一次对字符串的逆置。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是C++实现大整数进制转换的示例代码: ```cpp #include <iostream> #include <string> #include <algorithm> using namespace std; // 将字符串表示的数字换为整数数组 void str2num(string str, int num[], int &len, int &dot_pos, int &dot_len) { len = 0; dot_pos = -1; dot_len = 0; for (int i = 0; i < str.length(); i++) { if (str[i] == '.') { dot_pos = len; } else { num[len++] = str[i] - '0'; } } if (dot_pos != -1) { dot_len = len - dot_pos - 1; } } // 将整数数组换为字符串表示的数字 string num2str(int num[], int len, int dot_pos, int dot_len) { string str = ""; for (int i = 0; i < len; i++) { str += num[i] + '0'; if (i == dot_pos) { str += '.'; } } if (dot_pos == -1) { str += '.'; } for (int i = 0; i < dot_len; i++) { str += '0'; } return str; } // 将整数数组从from_base进制转换为to_base进制 void base_convert(int num[], int &len, int from_base, int to_base) { int new_num[1000], new_len = 0; while (len > 0) { int r = 0; for (int i = len - 1; i >= 0; i--) { int t = r * from_base + num[i]; num[i] = t / to_base; r = t % to_base; } new_num[new_len++] = r; while (len > 0 && num[len - 1] == 0) { len--; } } for (int i = 0; i < new_len; i++) { num[i] = new_num[new_len - i - 1]; } len = new_len; } int main() { string str; int from_base, to_base; cin >> str >> from_base >> to_base; int num[1000], len, dot_pos, dot_len; str2num(str, num, len, dot_pos, dot_len); // 将整数部分从from_base进制转换为10进制 int int_num[1000], int_len = 0; for (int i = 0; i < dot_pos; i++) { int r = 0; for (int j = int_len - 1; j >= 0; j--) { int t = r * from_base + int_num[j]; int_num[j] = t % 10; r = t / 10; } while (r > 0) { int_num[int_len++] = r % 10; r /= 10; } int_num[int_len++] = num[i]; } reverse(int_num, int_num + int_len); // 将小数部分从from_base进制转换为10进制 int dot_num[1000], dot_len = 0; for (int i = dot_pos + 1; i < len; i++) { int r = 0; for (int j = 0; j < dot_len; j++) { int t = r * from_base + dot_num[j]; dot_num[j] = t % 10; r = t / 10; } while (r > 0) { dot_num[dot_len++] = r % 10; r /= 10; } dot_num[dot_len++] = num[i]; } // 将整数部分和小数部分分别从10进制转换为to_base进制 base_convert(int_num, int_len, 10, to_base); base_convert(dot_num, dot_len, 10, to_base); // 将整数部分和小数部分合并为一个数组 for (int i = 0; i < int_len; i++) { num[i] = int_num[i]; } num[int_len++] = -1; for (int i = 0; i < dot_len; i++) { num[int_len++] = dot_num[i]; } // 将整个数组换为字符串表示的数字 str = num2str(num, int_len, dot_pos, dot_len); cout << str << endl; return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值