进制转换(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],一般对我来讲,因为用习惯了后面的那种拼接方式然后逆置整个串,就忽略了这样的拼接,这样的拼接就直接少了一次对字符串的逆置。

### C++ 中的进制转换方法 #### 使用字符串流 `stringstream` 实现进制转换C++ 中可以利用 `<sstream>` 库中的 `stringstream` 来方便地完成不同进制之间的换。下面是一个简单的例子展示如何将二进制字符串化为十进制数值[^1]。 ```cpp #include <iostream> #include <sstream> int binary_to_decimal(const std::string& binStr) { std::stringstream ss; int decimalValue = 0; // 将输入的二进制字符串放入 stringstream 并指定基数为2 ss << std::hex; // 如果是十六进制则应改为 hex ss << binStr; // 解析并得到对应的十进制值 ss >> decimalValue; return decimalValue; } int main() { std::string inputBinary = "1010"; // 假设这是要化成十进制的二进制数 int result = binary_to_decimal(inputBinary); std::cout << "The decimal value is: " << result << "\n"; } ``` 需要注意的是上述代码片段中对于二进制十进制换存在错误示范,实际操作时应当移除设置为十六进制的部分(`ss << std::hex`)以确保正确解析二进制字符串。 #### 手动计算法实现二进制十进制 另一种方式就是通过手动遍历每一位来进行加权求和从而获得最终的结果。这里给出一段具体的实现代码来说明这一过程[^2]: ```cpp #include <iostream> using namespace std; int main(){ string a; cin>>a;// 输入二进制数 int ans=0, jz=1, len=a.length(); for(int i=len-1;i>=0;i--){// 核心代码 ans += (a[i]-'0')*jz; jz *= 2; } cout<<ans;// 换成的十进制数 return 0; } ``` 此段代码展示了从右向左逐位处理的方式,并且每次迭代都将权重翻倍直到所有位都被考虑进去为止。 #### 多种格式间的相互换 除了基本类型的进制互换外,在某些应用场景下可能还需要支持更多样化的编码形式比如带符号表示等。有开发者分享了一个较为全面的支持多种编码间互相变的小工具[^3]: 这类程序通常会提供一组专门用于执行特定类型变换的操作接口,允许用户轻松地在这几种常见表达之间切换而无需担心底层细节。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值