高精度運算(大數加減乘除)階乘
阿新 • • 發佈:2019-01-27
大整數加法
string add(string s1,string s2)
{
string max,min;
if(s1.length()>s2.length())
{
max=s1;min=s2;
}
else
{
max=s2;min=s1;
}
int l1=max.length(),l2=min.length();
for(int i=l1-1,j=l2-1;j>=0;i--,j--)
max[i]+=min[j]-'0';
for(int i=l1-1 ;i>=1;i--)
if(max[i]>'9')
{
max[i]-=10;
max[i-1]++;
}
if(max[0]>'9')
{
max[0]-=10;
max='1'+max;
}
int i;
for(i=0;i<max.size();i++)
if(max[i]!='0')
break;
if(i==max.size())
return "0";
else
return max.erase(0,i);
}
大整數減法
#include <iostream>
#include <cstring>
using namespace std;
string a,b;
string substr(string a,string b )
{
int i,j,k,flag=1;
string s1,s2;
if(a.size()<b.size()||(a.size()==b.size()&&a.compare(b)<0))
{
//a的長度小於b的長度 或者 a的長度等於b的長度 a小於b
s1=a;
a=b;
b=s1;
flag=0;
}
//始 終 令 a 的 長 度 大 於 b 的長度
while (a.length()-1>b.length()-1) b='0'+b; //字元短的加前導零,使他們一樣長
for (i=a.length()-1; i>=1; i--) //減,規整 最高位單獨處理
{
if(a[i]>=b[i])
a[i]=a[i]-b[i]+'0';
else
{
a[i]=a[i]-b[i];
a[i]=a[i]+10+'0';
a[i-1]=a[i-1]-1;
}
}
a[0]=a[0]-b[0]+'0'; // a must more than b
//
// for( i=0; i<a.length(); i++)
// a[i]+=48;
for(i=0; i<a.length(); i++) // 去零 from high to low
if(a[i]!='0')
break;
if(i==a.length())
{
a="0";
return a;
}
for(j=i,k=0; j<a.length(); j++,k++)
s2=s2+a[j];
if(flag!=1)
{
s2='-'+s2;
}
return s2;
}
int main()
{
while(cin>>a>>b)
{
cout<<substr(a,b)<<endl;
}
return 0;
}
void mminus(char *str1,char *str2,char *str3)
{
int len1=strlen(str1),len2=strlen(str2);
len1--;
len2--;
int carry=0,casen=0;
while(len2>=0){
int temp=str1[len1]-str2[len2]-carry;
if(temp<0){
str3[casen++]=temp+10+'0';
carry=1;
}else{
str3[casen++]=temp+'0';
carry=0;
}
len1--;
len2--;
}
while(len1>=0){
int temp=str1[len1]-'0'-carry;
if(temp<0){
str3[casen++]=temp+10+'0';
carry=1;
}else{
str3[casen++]=temp+'0';
carry=0;
}
len1--;
}
casen--;
while(str3[casen]=='0'&&casen>0){
casen--;
}
str3[++casen]=0;
casen--;
for(int i=0;i<casen;i++,casen--){
char ch=str3[i];
str3[i]=str3[casen];
str3[casen]=ch;
}
return ;
}
大整數乘法 ##浮點數
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int main()
{
char s1[300],s2[300];
int sum[700],a[300],b[300];
while(scanf("%s%s",s1,s2)!=EOF)
{
// printf("%s\n%s\n",s1,s2);
memset(sum,0,sizeof(sum));
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
int k=0;
for(int i=strlen(s1)-1;i>=0;i--)
a[k++]=s1[i]-'0';
k=0;
for(int i=strlen(s2)-1;i>=0;i--)
b[k++]=s2[i]-'0';
for(int i=0;i<strlen(s1);i++)
for(int j=0;j<strlen(s2);j++)
sum[i+j]+=a[i]*b[j];
for(int i=0;i<strlen(s1)+strlen(s2);i++)
if(sum[i]>=10)
{
sum[i+1]+=sum[i]/10;
sum[i]%=10;
}
int j;
for(j=strlen(s1)+strlen(s2);j>=0;j--)
if(sum[j]==0)
continue;
else
break;
if(j<0)
printf("0");
else
for(int i=j;i>=0;i--)
printf("%d",sum[i]);
printf("\n");
}
return 0;
}
int sum[100000],a[100000],b[100000];
string cheng(string s1,string s2)
{
memset(sum,0,sizeof(sum));
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
int k=0;
// cout<<s1.size()<<" "<<s2.size()<<endl;
for(int i=s1.size()-1;i>=0;i--)
a[k++]=s1[i]-'0';
k=0;
for(int i=s2.size()-1;i>=0;i--)
b[k++]=s2[i]-'0';
for(int i=0;i<s1.size();i++)
for(int j=0;j<s2.size();j++)
sum[i+j]+=a[i]*b[j];
for(int i=0;i<s1.size()+s2.size();i++)
if(sum[i]>=10)
{
sum[i+1]+=sum[i]/10;
sum[i]%=10;
}
int j;
for(j=s1.size()+s2.size();j>=0;j--)
if(sum[j]==0)
continue;
else
break;
string s;
int len=0;
if(j<0)
s="0";
else
for(int i=j;i>=0;i--)
s.push_back(sum[i]+'0');
return s;
}
string Mult(string s,int x) //大數乘以整形數
{
reverse(s.begin(),s.end());
int cmp=0;
for(int i=0;i<s.size();i++)
{
cmp=(s[i]-'0')*x+cmp;
s[i]=(cmp%10+'0');
cmp/=10;
}
while(cmp)
{
s+=(cmp%10+'0');
cmp/=10;
}
reverse(s.begin(),s.end());
return s;
}
大整數除法
高精度除以高精度
#include<iostream>
#include<string>
using namespace std;
string rev(string a)
{
string ret=a;
int n=a.size();
for(int i=0;i<n/2;i++)
{
swap(ret[i],ret[n-i-1]);//得到逆序字串
}
return ret;
}
string add(string a,string b)//大整數加法
{
int lena=a.size();
int lenb=b.size();
a=rev(a);
b=rev(b);
int carry=0;
string c;
int i;
for(i=0;i<lena&&i<lenb;i++)
{
int ai=a[i]-'0';
int bi=b[i]-'0';
int ci=ai+bi+carry;
c+=(ci%10)+'0';//(ci%10)+'0'整體是一個字元,即(char)((ci%10)+'0')
carry=ci/10;
}
for(;i<lena;i++)
{
int ai=a[i]-'0';
int ci=ai+carry;
c+=(ci%10)+'0';
carry=ci/10;
}
for(;i<lenb;i++)
{
int bi=b[i]-'0';
int ci=bi+carry;
c+=(ci%10)+'0';
carry=ci/10;
}
if(carry==1) c=c+'1';
return rev(c);
}
string sub(string a,string b)
{
int lena=a.size();
int lenb=b.size();
if(lena<lenb||(lena==lenb&&a<b)) return "";
a=rev(a);
b=rev(b);
int carry=0;
string c;
int i;
for(i=0;i<lena&&i<lenb;i++)
{
int ai=a[i]-'0';
int bi=b[i]-'0';
int ci=ai-bi-carry;
if(ci<0)
{
ci+=10;
carry=1;
}
else carry=0;
c+=(ci%10)+'0';
}
for(;i<lena;i++)
{
int ai=a[i]-'0';
int ci=ai-carry;
if(ci<0)
{
ci+=10;
carry=1;
}
else carry=0;
c+=(ci%10)+'0';
}
int lenc=c.size();
for(i=c.size()-1;i>=0;i--)
{
if(c[i]=='0') lenc--;
else break;
}
if(lenc==0) return "";
c=c.substr(0,lenc);
return rev(c);
}
string divide(string a,string b)
{
int lena=a.size();
int lenb=b.size();
if(lena<lenb||(lena==lenb&&a<b)) return "0";
string bt[11];
bt[0]="";
bt[1]=b;
for(int j=2;j<=10;j++)//除法的條件限制每一位的商不可能>=10
{
bt[j]=add(bt[j-1],bt[1]);
}
int i=lenb-1;
string c;
string now=a.substr(0,lenb);
if(now<b)
{
now+=a[++i];//除法相當於多次減法,這樣表示++i程式更快
}
for(;i<lena;i++)
{
int ci;
int len_now=now.size();
for(ci=1;ci<=10;ci++)
{
int lbn=bt[ci].size();
if(lbn>len_now||(lbn==len_now&&bt[ci]>now)) break;//除不下去了就跳出迴圈
}
ci--;//看有幾個數能被減,因為ci時跳出迴圈,所以不算在內,需要減一
c+=ci+'0';
now=sub(now,bt[ci]);
if(i<lena-1)
{
if(now.size()==0&&a[i+1]=='0') continue;
now+=a[i+1];
}
}
return c;
}
int main()
{
string a,b;
cin>>a>>b;
cout<<divide(a,b)<<endl;
}
高精度除以低精度
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int a[100],c[100];
int main()
{
char bcs[100];
int b,lena,lenc,x,i;
gets(bcs);
cin>>b;
lena=strlen(bcs);
for(i=0;i<=lena-1;i++) a[i+1]=bcs[i]-'0';//從高位開始處理,所以儲存不同於加法減法乘法
//for(i=1;i<=lena;i++) cout<<a[i];
// cout<<endl; 驗證輸入處理有無問題
x=0;
for(i=1;i<=lena;i++) //核心程式碼 按位相除法
{
c[i]=(x*10+a[i])/b;
x=(x*10+a[i])%b;
}
lenc=1;
while(c[lenc]==0&&lenc<lena)//商不可能比被除數位數多
lenc++;//lenc指向第一個非零數
//cout<<lenc<<'\n';非零的超始輸出位數
for(i=lenc;i<=lena;i++) //輸出重點看起始值,需體會,從非零位輸出
cout<<c[i];
cout<<endl;
return 0;
}
高精度階乘
#include <bits/stdc++.h>
using namespace std;
typedef int INT;
const INT BASE = 1000000;
const int N = 1000;
INT digits[N];
int main()
{
int n;
while(scanf("%d", &n) != EOF) {
memset(digits, 0, sizeof(digits));
digits[0] = 1;
int len = 1;
for(int i = 2; i <= n; i++) {
INT carry = 0;
for(int j = 0; j < len; j++) {
digits[j] = digits[j] * i + carry;
carry = digits[j] / BASE;
digits[j] %= BASE;
}
if(carry)
digits[len++] = carry;
}
printf("%d!\n", n);
printf("%d", digits[len - 1]);
for(int i = len - 2; i >= 0; i--)
printf("%06d", digits[i]);
printf("\n");
}
return 0;
}
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int a[4000];//要麼為全域性變數
const double pi=acos(-1);
const double e=exp(1.0);
void solve(){
int n;
while(cin>>n){
for(int i=0;i<4000;i++){//要麼迭代賦值為0,使用memset會出現奇怪的錯誤
a[i]=0;
}
int r=0;//是否進位
a[0]=1;//這兒也很重要
for(int i=2;i<=n;i++){
for(int j=0;j<4000;j++){
a[j]=a[j]*i+r;
r=a[j]/10;//順序也很重要
a[j]%=10;
}
}
//斯特靈公式(求階乘位數)
int res=(int)(log10(2.0*pi*n)/2.0+n*log10(n/e)+1);
// cout<<res<<endl;
for(int i=res-1;i>=0;i--){
cout<<a[i];
}
cout<<endl;
}
}
int main()
{
solve();
return 0;
}