1. 程式人生 > >高精度運算(大數加減乘除)階乘

高精度運算(大數加減乘除)階乘

大整數加法

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;
}