一文解决 进制转化 (高精度+任意长度)

有帮助就点个赞呗👍

1. 入门–简单十进制转二进制代码模板

记住9=1*2^0+0*2^1+0*2^2+1*2^3
#include<bits/stdc++.h>
using namespace std;

//俩行关键代码搞定进制转换问题
void dectobin(int n)
{
    if(n==0)
        return;
    else
    {
        dectobin(n/2);
        cout<<n%2;
    }
}

int main()
{
    int n;
    while(cin>>n)
    {
        dectobin(n);
        cout<<endl;
    }
    return 0;
}

2. 进阶–十进制进制转化任意进制

#include<bits/stdc++.h>
using namespace std;

char bits[]={"0123456789ABCDEF"};
void convto(char *s,int n,int b)
{
    //边界判断
    if(n==0)
        return;
    
    //开始递归
    convto(s,n/b,b);
    int len=strlen(s);
    s[len]=bits[n%b];
    s[len+1]='\0';
}

int main()
{

    int n,b;
    char s[99]="";
    cin >> n;
    cin >> b;
    //n十进制数,b要转换的进制
    convto(s, n, b);
    cout << s << endl;
    return 0;
}

3. 进阶–任意长度十进制转二进制

3.1 基础知识–高精度加减乘除

高精度的加减乘除就只是 模拟与平时类似的手算而已

以下模板默认规定:

为计算方便,均采用Vector存储数据,并且数值的低位存在数组的高位,即123存储为,a[0]=3,a[1]=2,a[2]=3

3.1.1. 高精度加法

思路:

​ 从最低位开始加,每次相加前 把上一位的进位加进来,之后把结果存起来,并且更新进位

image-20221025153446753
#include<iostream>
#include<vector>

using namespace std;

//为了防止每次调用都得重新开一个空间存vector,加个&引用一下
vector<int> add(vector<int> &a,vector<int> &b)
{
    vector<int> c;
    int t=0;
    for(int i=0;i<a.size()||i<b.size();i++)
    {
        //不能非法越界
        if(i<a.size())  t+=a[i];
        if(i<b.size())  t+=b[i];
        
        //每一位的运算结果
        c.push_back(t%10);
        //进位
        t=t/10;
    }
    if(t==1) c.push_back(1);
    return c;
}
int main()
{
    vector<int> a,b;
    string m,n;
    cin>>m;
    cin>>n;
    
    for(int i=m.size()-1;i>=0;i--) a.push_back(m[i]-'0');
    for(int i=n.size()-1;i>=0;i--) b.push_back(n[i]-'0');
    
    auto c= add(a,b);
    
    for(int i=c.size()-1;i>=0;i--) 
        cout<<c[i];
    return 0;
}
3.1.2. 高精度减法

思路:

​ 与加法一样,计算前得先判断比较长度,每次相减前,把上一位的借位先减去,之后把结果存起来,并且更新借位

image-20221025153851970
#include<iostream>
#include<vector>

using namespace std;

//a>=b
bool cmp(vector<int> &a,vector<int> &b)
{
    //先判断长度
    if(a.size()!=b.size()) return a.size()>b.size();
    //再从高位往地位判断大小
    for(int i=a.size()-1;i>=0;i--)
        if(a[i]!=b[i])
            return a[i]>b[i];
    //最后就是相等的情况
    return 1;
}

vector<int> sub(vector<int> &a,vector<int> &b)
{
    vector<int> c;
    
    int i=0;//借位标志位
    for(int j=0;j<a.size();j++)
    {
        //同步借位标志位
        i=a[j]-i;
        //相当于把b[i]加上,即i=a[i]-b[i]-i
        if(b.size()>j) i-=b[j];
        //a%b返回正数值,(a%b+b)%b
        c.push_back((i%10+10)%10);
        
        //更新标志位
        if(i<0) i=1;
        else i=0;
    }
    //去掉前导0
    while(c.size()>1&&c.back()==0) c.pop_back();
    return c;
}
int main()
{
    string a,b;
    vector<int> A,B;
    cin>>a>>b;
    for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
    for(int i=b.size()-1;i>=0;i--) B.push_back(b[i]-'0');

    
    if(cmp(A,B))
    {
        auto c = sub(A,B);
        for(int i=c.size()-1;i>=0;i--) cout<<c[i];
    }
    else
    {
        auto c = sub(B,A);
        cout<<'-';
        for(int i=c.size()-1;i>=0;i--) cout<<c[i];
    }
    //cout<<cmp(A,B);
    return 0;
    
}
3.1.3. 高精度乘法

思路:

​ 主要是以A(大数)为基准,b(小数)当作一个整体,A的每一位乘以b的每一位即可

image-20221025154103048
#include<iostream>
#include<vector>

using namespace std;

vector<int> mul(vector<int> A,int b)
{
    vector<int> C;
    int t=0;
    for(int i=0;i<A.size()||t!=0;i++)
    {
        //把A的几个位数都乘了 并且加上进位
        if(i<A.size()) t+=A[i]*b;
        C.push_back(t%10);
        if(b==0) break;//去掉前导0
        //进位
        t/=10;
    }
    
    return C;
}
int main()
{
    string a;
    int b;
    vector<int> A;
    cin>>a>>b;
    for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
    
    auto C=mul(A,b);
    for(int i=C.size()-1;i>=0;i--) cout<<C[i];
    return 0;
}
3.1.4. 高精度除法

思路:

​ 与平常除法一样,模拟手算,一位一位除就行了,注意得加上上一位的余数

image-20221025154549181
#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

//    A/b=C...r       A为大数,b为被除数,r为余数
vector<int> dec(vector<int> &A,int b,int &r)
{
    vector<int> c;
    //注意这个得从最低位开始除
    for(int i=A.size()-1;i>=0;i--)
    {
        r=r*10+A[i];
        c.push_back(r/b);
        r=r%b;
    }
    reverse(c.begin(),c.end());
    while(c.size()>1&&c.back()==0) c.pop_back();
    
    return c;
}

int main()
{
    string a;
    vector<int> A;
    int b;
    cin>>a>>b;
    for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
    
    int r=0;
    auto c=dec(A,b,r);
    for(int i=c.size()-1;i>=0;i--) cout<<c[i];
    cout<<endl<<r<<endl;
}

3.2 正式解题

题目链接:https://www.acwing.com/problem/content/description/3376/

递归将十进制转为二进制,配合一个高精度除法即可

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

//    A/b=C...r       A为大数,b为被除数,r为余数
vector<int> dec(vector<int> &A,int b,int &r)
{
    vector<int> c;
    //注意这个得从最低位开始除
    for(int i=A.size()-1;i>=0;i--)
    {
        r=r*10+A[i];
        c.push_back(r/b);
        r=r%b;
    }
    reverse(c.begin(),c.end());
    while(c.size()>1&&c.back()==0) c.pop_back();
    
    return c;
}

void convert(vector<int> c)
{
    if(c.size()==1&&c.back()==0)
        return;
    else
    {
        int r=0;
        auto a=dec(c,2,r);
        convert(a);
        cout<<r;
    }
}

int main()
{
    string a;

    while(cin>>a)
    {
        vector<int> A;
        for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
        
        int r=0;
        if(A.size()==1&&A.back()==0) 
        {
            cout<<0<<endl;
            continue;
        }
        convert(A);
        cout<<endl;
    }
}

4. 进阶–任意长度十进制进制反转

题目链接:https://www.acwing.com/problem/content/description/3398/

利用前面所学知识,即可实现十进制反转

直接暴力十进制转二进制,之后再转为十进制即可
但是!输入的数据,有足足1000位,而int只能存下32位,因此得使用高精度的算法来求解

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
vector<int> cnt;//用来存递归的数据

//高精度除法
//  A/b=C...r   A为大数,b为被除数,r为余数
vector<int> dec(vector<int> &A,int b,int &r)
{
    vector<int> c;
    //注意这个得从最低位开始除
    for(int i=A.size()-1;i>=0;i--)
    {
        r=r*10+A[i];
        c.push_back(r/b);
        r=r%b;
    }
    reverse(c.begin(),c.end());
    while(c.size()>1&&c.back()==0) c.pop_back();
    
    return c;
}

//高精度加法
vector<int> add(vector<int> &a,vector<int> &b)
{
    vector<int> c;
    int t=0;
    for(int i=0;i<a.size()||i<b.size();i++)
    {
        //不能非法越界
        if(i<a.size())  t+=a[i];
        if(i<b.size())  t+=b[i];
        
        //每一位的运算结果
        c.push_back(t%10);
        //进位
        t=t/10;
    }
    if(t==1) c.push_back(1);
    return c;
}


//二进制转十进制,遍历
vector<int> convert_2to10(vector<int> a)
{
    vector<int> sum;
    vector<int> wight;
    wight.push_back(1);
    for(int i=0;i<a.size();i++)
    {
        if(a[i]==1)
            sum=add(sum,wight);
        wight=add(wight,wight);
    }
    return sum;
}

//十进制转二进制,递归
void convert_10to2(vector<int> c)
{
    if(c.size()==1&&c.back()==0)
        return;
    else
    {
        int r=0;
        auto a=dec(c,2,r);
        convert_10to2(a);
        cnt.push_back(r);
    }
}

int main()
{
    string a;
    cin>>a;

    vector<int> A;
    for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
    
    int r=0;
    
    //特殊值0的判断
    if(A.size()==1&&A.back()==0) 
    {
        cout<<0<<endl;
        return 0;
    }
    
    convert_10to2(A);
    
    auto sum=convert_2to10(cnt);
    
    for(int i=sum.size()-1;i>=0;i--) cout<<sum[i];

    return 0;
}

其他:个人博客,欢迎参观🤭


                    难得写个笔记,点个赞再走呗~
                             肥肠感谢!
                                😁
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值