高精度计算(六)除法

高精除

高精除看起来很复杂                                                                  
实际上就是一个 对位相减 的过程 因为是 对位相减 理论复杂度很小不会T
(这里介绍高精除高精,高精除低精相对简单,拿一个中间变量记一下就好了)
基本思想
还是考虑小学课堂的除法 下面看竖式
回想做除法竖式的情景 是不是先把27放到2835的最前面和28作比较看谁大谁小

如果除数小于被除数的当前串那么就向上商答案商到被除数的当前串小于除数

在实际操作中可以用减法来模拟这个过程 每减一次就在对应除数尾部答案处加一来统计答案

还是举个例子:看上式,27在28处查看发现我比28!那么进行一次减法操作使得2 8 - 2 7现在被除数变成1 3 5

再次查看时发现27比1要了 此时不能再减 则将除数(2 7)的指针向后移 到了1 3的位置 发现还是小 指针再向后移动
到了3 5处 统计从头到指针的数字(即0 1 3 5)与除数(2 7)进行比较 发现可以操作 那么就进行减法操作

每次减完后都检查是否能继续减下去 然后ans[tail]++ 统计答案 tail即是尾指针
代码
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

#define tail head+len2-1//与head联动的tail 记录除数的尾部指针 
#define Init len1=strlen(s1+1),len2=strlen(s2+1);//初始化 

const int Maxn=10001;

int len1,len2,cur=1;
char s1[Maxn],s2[Maxn];
int a[Maxn],b[Maxn],c[Maxn],ans[Maxn];

bool compare(int head)
{
	cur=1;while(a[cur]==0)cur++;//去除a前面的0 便于计算 
	if(tail-cur+1 > len2)return 1;//tail-cur+1即是当前串的长度 
	if(tail-cur+1 < len2)return 0;
	string str1="",str2="";//比大小 
	for(int i=cur;i<=tail;i++){
		str1 += a[i]+48;
		str2 += b[i-head+1]+48;
	}
	if(str1>=str2)return 1;//使用重载过的String类比较 
	else return 0;//如果大于等于就减 小于则不能减 
}

int sub(int head)
{
	for(int i=tail;i>=tail-len2+1;i--){//从后往前减 
		a[i]=a[i]-b[i-head+1];//减法 
		if(a[i]<0){//如果不够减借一位 
			a[i]+=10;
			a[i-1]--;
		}
	}
	ans[tail]++;//统计答案 
}

int main()
{
	scanf("%s%s",s1+1,s2+1);Init//读入并处理出长度 
	for(int i=1;i<=len1;i++)a[i] = s1[i]-'0';//读入 
	for(int i=1;i<=len2;i++)b[i] = s2[i]-'0';//读入 
	for(int head=1;tail<=len1;head++){//查看该数放在哪一个位置 
		if( !compare(head) )continue;//如果a小于b 则继续下一层 即把b数往后挪一位 
		else while( compare(head) ) sub(head);//只要能减就一直减 直到a小于b 同时在tail处统计答案 
	}
	cur=1;while( ans[cur]==0 && cur!=len1 )cur++;//去除前面的0 
	for(int i=cur;i<=len1;i++)printf("%d",ans[i]);//输出 
}


 

欢迎指出Bug

End。


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值