主要分为5个方面来开展:
1.高精度数的存储,我是按照《晴神宝典》的用一个包含int数组和表示长度int的struct bign来存储数据,当然了,为了方便,我们存储方向和我们正常的数字大小排列方向相反,我们是数组低位存放阶数小的数字,这样方便之后的计算
2.加法,加法应该就是直接模拟,记得用一个carry来存放进位就行了,其他的没有什么好说
2.减法,减法的话就是多了个向高处借位,既高一位的地方-1,自己位置+10,最后要消除前导0
4.乘法,乘法也是简单模拟,两个数的每一位和每一位相乘,然后再相加
5.除法,除法是最难的一个,虽然也是模拟,但是你使用高精度数除以一个高精度数的时候还是有点难度,首先整个模拟过程要清晰:
输入的被除数a,除数b
每一个循环的被除数=余数*10+当前位置数,用被除数除以除数(除数即为我们输入的除数b),如果
(1)够除的话,那就得到商,和新的余数
(2)如果不够除,就直接把被除数赋给余数
进入下一个循环,直至a的位数都用完
这里有一个技巧就是(1)中要怎么除,因为是高精度除以高精度,所以没办法使用内置除法,故此处使用减法来模拟除法(即不断地去减,直至减不了)
#include<iostream> #include<stdio.h> #include<string> #include<cstring> using namespace std; const int max_size=1000; struct bign{ int d[max_size]; int len; bign(){ len=0; memset(d,0,sizeof(d)); } }; bign to_bign(string str){ bign big; int size=str.size(); big.len=size; for(int i=0;i!=size;++i) big.d[i]=str[size-1-i]-‘0‘; //注意这里是string的char转化为int,要用-‘0‘变通一下 return big; } bign add(bign a,bign b){ bign c; int carry=0; for(int i=0;i<=a.len-1 || i<=b.len-1;++i){ int temp=carry+a.d[i]+b.d[i]; c.d[c.len++]=temp%10; carry=temp/10; } if(carry!=0){ c.d[c.len++]=carry; } return c; } int cmp(bign a,bign b){ int i; if(a.len>=b.len) i=a.len; else i=b.len; for(;i>=0;i--){ if(a.d[i]>b.d[i]) return 1; else if(a.d[i]<b.d[i]) return -1; } return 0; } bign sub(bign a,bign b){ //a-b, 保证a>b bign c; for(int i=0;i<a.len;++i){ //a肯定是长的那一个 if(a.d[i]-b.d[i]<0){ a.d[i+1]--; a.d[i]+=10; } c.d[c.len++]=a.d[i]-b.d[i]; } //消除前导0 while(c.len-1>=1 && c.d[c.len-1]==0){ c.len--; } return c; } bign multi(bign a,bign b){ bign c; for(int i=0;i<a.len;++i){ int m=a.d[i]; for(int j=0;j<b.len;++j){ int temp=c.d[i+j]+m*b.d[j]; c.d[i+j]=temp%10; c.d[i+j+1]+=temp/10; } } if(c.d[a.len+b.len-1]!=0) c.len=a.len+b.len; else c.len=a.len+b.len-1; return c; } //高精度除以高精度,好难写啊,原来我是卡在用减法模拟除法那里了 bign result_n; bign remain_n; bign division(bign a,bign b){ //a/b int bits=b.len; bign remain; bign sub1; string result_str; for(int i=a.len-1;i>=0;--i){ remain=multi(remain,to_bign("10")); //余数*10 string str; str+=(‘0‘+a.d[i]); sub1=add(remain,to_bign(str)); int if_bigger=cmp(sub1,b); if(if_bigger>=0){ //法模拟除法 int count=0; while(cmp(sub1,b)>=0){ sub1=sub(sub1,b); count++; } result_str+=(‘0‘+count); //存下商 remain=sub1; //保留此次余数 } else{ remain=sub1; } } result_n=to_bign(result_str); remain_n=remain; } void print_bign(bign b){ for(int i=b.len-1;i>=0;--i) printf("%d",b.d[i]); } int main(){ freopen("in.txt","r",stdin); string str1,str2; cin>>str1>>str2; //string对象的读写还是用cin>>string和cout<<string,不要用scanf,printf,不然有问题 bign b1=to_bign(str1); bign b2=to_bign(str2); division(b1,b2); print_bign(result_n); printf(" "); print_bign(remain_n); return 0; }
原文地址:https://www.cnblogs.com/chuan-chuan/p/11498452.html
时间: 2024-11-06 03:37:27