作者留言:初学者写的代码,想法和代码可能会比较低端,正在改进中,大佬可以给点建议~~
实现目的:在运算一些长度较长的数字,而计算机的运算范围不足以实现运算要求时,实行高精度运算。这里主要解决减法运算。
运算原理:因为数字长度过长,无法通过直接的相减以实现要求,所以引入了字符串,通过把每一位数字存进字符串,对每一位字符串的相减得出结果。
主要思路:任意两数相减,有很多的情况。所以要分5步操作。
一.区分大小:那么首先要区分大数和小数,这里主要通过区分存入字符串的长度来区分,字符串长的则大,字符串短的则小,当字符串相等的时候,先找出从高位到低位第一个不相等位数,再判别两数在此位数的大小,大的则大,小的则小,若是相等则直接输出0,不需要进入代码区中的相减运算,否则会触发下面讲到的去前导0的bug。(当两个数相等时:例如100-100 根据计算结果会为000,若去前导0,则会把3个0全部去掉,所以无需去前导0,直接输出0)
二.转型存放:区分完大小,要将两个字符串变成整型倒序存放进容器,因为设置的容器A和B总是以大减小,所以大数放A容器,小数放B容器。然后输出的结果则设置为C容器。
三.运算设置:设置相减调用区,相减的原理则是对位相减,对位上都有数字直接减,不够减则借位+10,被借位-1,得出的数再插进C容器;若是对位上只剩下较大的数,且较大的数上的位数不为负数,若为负数也要借位+10,被借位-1,再插入C容器。
四.去前导0操作:最后会得到一个C容器,C容器中的数字并不是我们所要的答案,首先我们需要去掉前导0,把最前面不要的0去掉。
五.输出:由于我们是倒序存放数字,所以再输出的时候也需要倒序输出。在输出的时候应该注意,若输出的第一个数小于第二个数,则需要在倒序输出C容器前面先输出“-”符号。因为在步骤二中我们无论怎样都是把较大的数放进A容器,较小的数存在B容器,得出的结果始终是正数。若输出的第一个数大于等于第二个数,直接倒序输出。
主要事项:详细见代码区
涉及重要的一些知识点:
1.容器的定义和对容器中插入的操作(3中有删除操作)
vector<int>A;//定义A容器 A.push_back(1);//将1插入A容器的尾部
2.整型和字符型之间的转换
字符型转化为整型
string a;//定义a为字符串 cin>>a;//输入a a[i]=a[i]-'0';// 把字符串的每一个变成整型,可以直接使用,详细见代码区的使用
整形转化为字符型
itoa()原型: char *itoa( int value, char *string,int radix); 原型说明: 输入参数: value:要转换的数据。 string:目标字符串的地址。 radix:转换后的进制数,可以是10进制、16进制等,范围必须在 2-36。 功能:将整数value 转换成字符串存入string 指向的内存空间 ,radix 为转换时所用基数(保存到字符串中的数据的进制基数)。 返回值:函数返回一个指向 str,无错误返回。 注意:itoa不是一个标准的c函数,他是windows特有的,跨平台写程序,要用sprintf。 使用例子: #include<iostream> #include<cstdlib> #include<cstdio> using namespace std; int main(){ int number = 123456; char str[20]; itoa(number,str,10); printf("integer=%d,string=%s\n",number,str); cout<<"str[0]: "<<str[0]<<endl; }
3.去前导0的实现
方法一:(if语句和for循环)
int last; for(int i=C.size()-1;i>=0;i--) { if(C[i]!=0) { last=i; //标记第一个不是0的位数 break; } //从第一个不是0的开始输出 for(int i=last;i>=0;i--) cout<<C[i]; }
方法二:(while循环和,back()和pop的结合使用)
while(C.size()>1&&C.back()==0) C.pop_back(); //当长度大于1并且上一位是0的时候就把最后的0删除,长度大于1的目的是防止答案为0 //push用于插入 pop用于删除
4.字符串长度和容器长度的使用方法
vector<int>A; A.size();//表示容器A的长度 string a; a.size();//表示字符串的长度
源代码:
#include<bits/stdc++.h>
#include<string>
using namespace std;
//此时容器A存放的都是较大的数字,B容器存放的都是较小的数字
vector<int> sub(vector<int> A,vector<int> B) //两个容器相减
{
vector<int>C;
for(int i=0;i<A.size()||i<B.size();i++)
{
if((i<A.size())&&(i<B.size())) //此时检查的位数两个容器都有数
{
if((A[i]<B[i])) //当此时A容器的数不够B容器减的时候
{
A[i]+=10; //先给A容器加10
C.push_back(A[i]-B[i]);
A[i+1]-=1; //因为前面加10,所以下一位就要减1
}
else C.push_back(A[i]-B[i]);
}
if((i<=A.size())&&(i>=B.size())) //此时检查的位数A容器还有,但是B容器已经没有,就直接输出A容器的数字
{
if(A[i]<0) {A[i]+=10; A[i+1]-=1;} //如果此时的数字正好是0,又被前面的数字借走导致成为负数,就加10,往后数-1;
C.push_back(A[i]);
}
}
return C;
}
int main()
{
string a,b; //定义两个字符串
vector<int>A,B; //定义两个容器存放字符串
cin>>a>>b; //输入字符串
if(a.size()!=b.size())
{
if(a.size()>b.size()) //当第一个数的长度比第二个数的长度长
{
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'); //同上
vector<int>C=sub(A,B);
//去前导0
int last;
for(int i=C.size()-1;i>=0;i--)
{
if(C[i]!=0)
{last=i; //标记第一个不是0的位数
break;
}
}
//输出
for(int i=last;i>=0;i--)
cout<<C[i];
}
//当第一个数的长度比第二个数的长度段
if(a.size()<b.size())
{
//存放的容器对调
for(int i=a.size()-1;i>=0;i-- ) B.push_back(a[i]-'0');//将字符串转化为数字,此时
for(int i=b.size()-1;i>=0;i--) A.push_back(b[i]-'0'); //同上
vector<int>C=sub(A,B);
//去前导0
int last;
for(int i=C.size()-1;i>=0;i--)
{
if(C[i]!=0)
{last=i; //标记第一个不是0的位数
break;
}
}
//输出
//因为第一个数小于第二个数,所以要输出负号
cout<<"-";
for(int i=last;i>=0;i--)
cout<<C[i];
}
}
//当两个位数相等时
if(a.size()==b.size())
{
int rem=0;
int flag=0;
//两个位数相等,所以要找到两个数从高位到低位第一个不同的数字
for(int i=0;i<a.size();i++)
{
if(a[i]!=b[i]) { rem=i;flag++; break;}//有不同数字,flag++,说明rem被赋值
}
//若第一个数大于第二个数
if(flag!=0&&a[rem]>b[rem])
{
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'); //同上
vector<int>C=sub(A,B);
//去前导0
int last;
for(int i=C.size()-1;i>=0;i--)
{
if(C[i]!=0)
{
last=i; //标记第一个不是0的位数
break;
}
}
//输出
for(int i=last;i>=0;i--)
cout<<C[i];
}
//若第一个数小于第二个数
if(flag!=0&&a[rem]<b[rem])
{
for(int i=a.size()-1;i>=0;i-- ) B.push_back(a[i]-'0');//将字符串转化为数字
for(int i=b.size()-1;i>=0;i--) A.push_back(b[i]-'0'); //同上
vector<int>C=sub(A,B);
//去前导0
int last;
for(int i=C.size()-1;i>=0;i--)
{
if(C[i]!=0)
{
last=i; //标记第一个不是0的位数
break;}
}
//输出
cout<<"-";
for(int i=last;i>=0;i--)
cout<<C[i];
}
//检查到最后若是都相同 ,flag==0,说明rem没有被赋值,两数完全相等
if(flag==0) cout<<"0"; //当两个数完全相同时,会输出a长度个 0,再进行去除前导0会没有数值 ,所以此时直接输出0
}
return 0;
}