大家好,我是屁孩君,今天跟大家来分享一下高精度!
省流:直接康完整代码
前言
在学习c++的路程中,我们总会遇到有些题的数据范围超出了int,long ,long long…这时我们就需要使用大招:高精度加法!!!
提示:以下是本篇文章正文内容
算法
高精度呢,输入时是使用字符串的,再把它存入输组。
高精度加法:
将两个字符串输入,逆序存入数组,然后使用for循环逐位相加,相加的结果存入c数组,再进位,最后逆序输出。比如说142+256
用高精度呢,就变成了这样!
高精度减法:
将两个字符串读入,逆序存入数组,使用for循环逐位相减,将差存入c数组,不够就向后一位借,再从后往前遍历判断c数组的第一个非0元素的位置,把位置存入变量里,最后逆序输出。
比如说456-142。
我们使用高精度呢,就变成了this
当然了,还有一种要借位的就有大家去自行模拟了!
高精度乘单精度:单精度不超过10000(题目所示)
将一个字符串读入(因为另一个数是单精度,不用字符串),逆序存入数组,然后把单精度的数当成一个数,用高精度的每一位去乘单精度,把积存入c数组,再进位(注:一个高精度的数乘一个小于等于10000的数,即最多多4位,切记不要忘记去进那四位),再从后往前遍历判断c数组的第一个非0元素的位置,把位置存入变量里,最后逆序输出。
比如说:99910
使用高精度后,摇身一变
因为这压根就没变所以我就先不列了(趁机偷懒 )
但是大家发现了吗,其实高精度几乎差不多,只是轻微的改变了一下。
高精度除法:
使用for循环重复输出就ok了细分的简单。
高精乘:
将两个字符串读入,逆序存入数组,a数组的每一位都与b[j]乘,积错位存入c数组,比如说一个乘数的下标是0,另一个乘数的下标是3,那他们的积的下标则为0+3,也就要存入c[3]中,然后进位,再从后往前遍历判断c数组的第一个非0元素的位置,把位置存入变量里,最后逆序输出
比如说456789
使用高精度算法后就变成了this
简单来说就是乘的方向变了一下。
分步完成
高精度加法:
1:输入字符串。
cin>>s1>>s2;
2: 将字符串逆序存储到数组里。
for(int i=0;i<s1.size();i++)
{
a[s1.size()-(i+1)]=s1[i]-'0';
}
for(int i=0;i<s2.size();i++)
{
b[s2.size()-(i+1)]=s2[i]-'0';
}
3:把两个数组值相加
for(int i=0;i<len;i++)
{
c[i]=a[i]+b[i];
}
4:逆序输出
for(int i=len-1;i>=0;i--)cout<<c[i];
高精度减法:
1:判断结果正负
if(s1.size()<s2.size()||(s1.size()==s2.size()&&s1<s2))
{
q='-';//如果是负数得把符号改成-
swap(s1,s2);//交换位置
}
2:逆序存入数组
for(int i=0;i<s1.size();i++)
{
a[i]=s1[s1.size()-i-1]-'0';
}
for(int i=0;i<s2.size();i++)
{
b[i]=s2[s2.size()-i-1]-'0';
}
3:从左到右逐个减
for(int i=0;i<s1.size();i++)
{
if(a[i]<b[i])
{
a[i+1]-=1;
a[i]+=10;
}
c[i]=a[i]-b[i];
}
4:逆序输出
for(int i=len-1;i>=0;i--)if(c[i]!=0){//重要代码,找出不是0的位置
p=i;break;
}
for(int i=p;i>=0;i--)cout<<c[i];//逆序输出
高精度乘单精度:
1:将字符串逆序存入数组
cin>>s1>>b;
for(int i=0;i<s1.size();i++)
{
a[i]=s1[s1.size()-i-1]-'0';
}
2:逐位乘
for(int i=0;i<s1.size();i++)
{
a[i]*=b;//把b看成一个数,将b与a数组逐位相乘
}
3:逐位进位
for(int i=0;i<s1.size()+4;i++)
{
if(a[i]>=10)
{
a[i+1]+=a[i]/10;//满十进一
a[i]%=10;
}
}
4:判断几位数,从那个位置开始逆序输出
for(int i=s1.size()+3;i>=0;i--)
{
if(a[i]!=0)
{
p=i;//记录位置
break;//记得终止循环
}
}
5:逆序输出
for(int i=p;i>=0;i--)cout<<a[i];
高精度除法:
1:输出整数部分
cout<<a/b<<'.';
2:反复循环输出小数部分
for(int i=0;i<n;i++)
{
t*=10;
cout<<t/b;
t=t%b;
}
高精度乘:
1:将两个字符串逆序存入数组a与数组b
for(i=0;i<s1.size();i++)
{
a[i]=s1[s1.size()-i-1]-'0';
}
for(i=0;i<s2.size();i++)
{
b[i]=s2[s2.size()-i-1]-'0';
}
2:用a[i]去乘以b[j]
这个大家都会吧!
3:错位加到c数组里
c[i+j]=c[i+j]+a[i]*b[j];
4:从数组的最后面往前面遍历,找到第一个非零元素,简单的来讲就是第一个有数的位置
for(i=s1.size()+s2.size()-1;i>=0;i--)
{
if(c[i]!=0){
p=i;
break;
}
}
5:逆序输出
for(int i=len-1;i>=0;i--)cout<<c[i];
完整代码
高精度加法:
#include<bits/stdc++.h>
using namespace std;
string a1,b1;
int a[250],b[250],c[500];
int main()
{
cin>>a1>>b1;
for(int i=0;i<a1.size();i++)
{
a[i]=a1[a1.size()-i-1]-'0';
}
for(int i=0;i<b1.size();i++)
{
b[i]=b1[b1.size()-i-1]-'0';
}
int len=max(a1.size(),b1.size());
for(int i=0;i<len;i++)
{
c[i]+=a[i]+b[i];
if(c[i]>=10)
{
c[i+1]+=c[i]/10;
c[i]%=10;
}
}
if(c[len]!=0)len++;
for(int i=len-1;i>=0;i--)cout<<c[i];
return 0;
}
高精度减法:
#include<bits/stdc++.h>
using namespace std;
string a1,b1;
int a[250],b[250],c[250];
char q='+';
int main()
{
int p=0;
cin>>a1>>b1;
if(a1.size()<b1.size()||(a1.size()==b1.size()&&a1<b1))
{
q='-';
swap(a1,b1);
}
for(int i=0;i<a1.size();i++)
{
a[i]=a1[a1.size()-i-1]-'0';
}
for(int i=0;i<b1.size();i++)
{
b[i]=b1[b1.size()-i-1]-'0';
}
for(int i=0;i<a1.size();i++)
{
if(a[i]<b[i])
{
a[i+1]-=1;
a[i]+=10;
}
c[i]=a[i]-b[i];
}
if(q=='-')cout<<'-';
for(int i=a1.size();i>=0;i--)
{
if(c[i]!=0)
{
p=i;
break;
}
}
for(int i=p;i>=0;i--)cout<<c[i];
return 0;
}
高精度乘单精度:
#include<bits/stdc++.h>
using namespace std;
string s1;
int a[250],b;
int main()
{
int p;
cin>>s1>>b;
for(int i=0;i<s1.size();i++)
{
a[i]=s1[s1.size()-i-1]-'0';
}
for(int i=0;i<s1.size();i++)
{
a[i]*=b;
}
for(int i=0;i<s1.size()+4;i++)
{
if(a[i]>=10)
{
a[i+1]+=a[i]/10;
a[i]%=10;
}
}
for(int i=s1.size()+3;i>=0;i--)
{
if(a[i]!=0)
{
p=i;
break;
}
}
for(int i=p;i>=0;i--)cout<<a[i];
return 0;
}
高精度除法:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int a,b,n,t;
cin>>a>>b>>n;
t=a%b;
cout<<a/b<<'.';
for(int i=0;i<n;i++)
{
t*=10;
cout<<t/b;
t=t%b;
}
return 0;
}
高精度乘:
#include<bits/stdc++.h>
using namespace std;
string s1,s2;
int a[250],b[250],c[500],i,j;
int main()
{
int p;
cin>>s1>>s2;
for(i=0;i<s1.size();i++)
{
a[i]=s1[s1.size()-i-1]-'0';
}
for(i=0;i<s2.size();i++)
{
b[i]=s2[s2.size()-i-1]-'0';
}
for(i=0;i<s1.size();i++)
{
for(j=0;j<s2.size();j++)
{
c[i+j]=c[i+j]+a[i]*b[j];
if(c[i+j]>=10)
{
c[i+j+1]+=c[i+j]/10;
c[i+j]%=10;
}
}
}
for(i=s1.size()+s2.size()-1;i>=0;i--)
{
if(c[i]!=0){
p=i;
break;
}
}
for(i=p;i>=0;i--)
{
cout<<c[i];
}
return 0;
}
实战应用
题目描述
求2+22+222+…+222…*2的和是多少?最后一项有多少2相乘由键盘读入的n决定(1<=n<=100)!
比如:n=3,那么s=2+22+22*2=14!
输入
从键盘读入一个整数n(1<=n<=100)
输出
输出求出的和
样例
输入
3
输出
14
这题呢其实就是把高精度加法和乘法融合在了一起,我们呢就开两个数组,一个是哪来存储每次加的值的,一个是用来存和的,每次把存加的值的数组的每个元素都成2。
1.将a数组的a[0]元素设为1,不然怎么乘都是0。
a[0]=1;
2.将储存每次加的值的数组每位上都乘二
for(int j=0;j<k;j++)
{
a[j]*=2;
}
3.将储存每次加的值的数组进位
for(int j=0;j<k;j++)
{
if(a[j]>=10){
a[j+1]+=a[j]/10;
a[j]%=10;
}
}
4.判断位数,如果第k位不为零,就将数组位数加一。
if(a[k]!=0)k++;
5.将存和的数组加上存储每次加的值的数组的值
for(int j=0;j<len;j++)
{
b[j]+=a[j];
if(b[j]>=10)
{
b[j+1]+=b[j]/10;
b[j]%=10;
}
}
6.逆序输出
for(int i=len-1;i>=0;i--)
{
cout<<b[i];
}
话不多说,直接上完整代码
#include<bits/stdc++.h>
using namespace std;
int a[5000];
int b[5000];
int main()
{
int n,k=1,k2=1,len;
cin>>n;
a[0]=1;
for(int i=1;i<=n;i++)
{
for(int j=0;j<k;j++)
{
a[j]*=2;
}
for(int j=0;j<k;j++)
{
if(a[j]>=10){
a[j+1]+=a[j]/10;
a[j]%=10;
}
}
if(a[k]!=0)k++;
len=k;
if(len<k2)len=k2;
for(int j=0;j<len;j++)
{
b[j]+=a[j];
if(b[j]>=10)
{
b[j+1]+=b[j]/10;
b[j]%=10;
}
}
if(b[len]!=0)len++;
}
for(int i=len-1;i>=0;i--)
{
cout<<b[i];
}
return 0;
}
题目描述
请计算n的阶乘(1<=n<=100)
n的阶乘计算公式为:n!=n*(n-1)(n-2)…1,如:5!=5432*1=120
输入
一个整数n(1<=n<=100)
输出
n的
样例
输入
20
输出
2432902008176640000
直接上完整代码
这题其实就是高精度乘法的plus版,只不过另一个乘数一直在变而已了。
1.将a数组的a[0]元素设为1,不然怎么乘都是0。
a[0] = 1;
2.将另一个乘数慢慢减
for (int i = n; i >= 1; i--)
3.将a数组的每一位都乘另一个乘数
for (int j = 0; j < k; j++)
{
a[j] *= i;
}
4.进位
for (int j = 0; j < k; j++)
{
if (a[j] >= 10) {
a[j + 1] += a[j] / 10;
a[j] %= 10;
}
if (a[k] != 0)k++;
}
5.逆序输出
for (int i = k - 1; i >= 0; i--)
{
cout << a[i];
}
#include<iostream>
using namespace std;
int a[5000];
int main()
{
int n,k=1;
cin >> n;
a[0] = 1;
for (int i = n; i >= 1; i--)
{
for (int j = 0; j < k; j++)
{
a[j] *= i;
}
for (int j = 0; j < k; j++)
{
if (a[j] >= 10) {
a[j + 1] += a[j] / 10;
a[j] %= 10;
}
if (a[k] != 0)k++;
}
}
for (int i = k - 1; i >= 0; i--)
{
cout << a[i];
}
return 0;
}
总结(注意事项)
总而言之,高精度的过程最好的理解办法就是画图,列竖式。
高精度的各种算法大体是相同的,比如说逆序存入数组,进位,逆序输出,判断第一个非零元素…
高精度的细节还是很多的,一步错,步步错。高精度的题目呢一般都是高精度基本的plus版,有些题呢需要几种高精度算法组合起来使用。
高精度大家一定要好好的理解,不要走马观花!!!
今天就给大家分享到这里了!!!
古德拜!!!
记得三连哦!!!