高精除高精

高精除以高精

高精除以高精,求它们的商和余数。

算法分析

高精除以低精是对被除数的每一位都除以除数,(和高精加减乘不一样,高精的被除数不需要倒序存储在int数组中),而高精除以高精则是用减法模拟除法,对被除数的每一位都减去除数,一直减到当前位置的数字小于除数:

举个栗子

计算a/b,a是1234,b是56.正确结果应该是商22,余2.
采用一直减的过程用计算器截图如下:
数一下一共减去22次56剩下的数是2,2<56
数一下1234一共减去22次56剩下的数是2,2<56,因此商是22,余数是2.

参考代码1(一本通只能得33分,经过一个测试点)

#include<cstdio>
#include<cstring>

int  a[350],b[350];
long long c;
int lena,lenb;
void init(int x[])
{
	char aa[350];
	scanf("%s",aa);
	int len=strlen(aa);
	for(int i=0;i<len;i++)
	   x[len-i]=aa[i]-'0';
	x[0]=len;
}
int cmp(int a[],int b[])//a大于b就返回1,等于就返回0 小于就返回-1 
{
	if(a[0]>b[0]) return 1;
	if(a[0]<b[0]) return -1;
	for(int i=a[0];i>=1;i--)//两个数组长度一样,则依次比较到底哪个数组的值更大 
	{
		if(a[i]>b[i]) return 1;
		if(a[i]<b[i]) return -1;
	}
	return 0;//默认就是a和b是相等的 
}
void gjj(int a[],int b[])
{
	int flag;flag=cmp(a,b);
	if(flag==0) {
		a[0]=0;return;
	} 
	if(flag==1){
		for(int i=1;i<=a[0];i++)
	    {
		   if(a[i]<b[i])
		  {
			a[i]+=10;
			a[i+1]--;
	    	}
	       a[i]=a[i]-b[i];	//得到新的a数组的值 
    	}
		while(a[a[0]]==0&&a[0]>0) a[0]--;
		return;	
	}
}
void chugao(int a[],int b[])
{
	while(cmp(a,b)>=0) {
		c++;//记录除了多少次 ,但是如果这个次数精度也非常高,这样处理就是不行的。 
		gjj(a,b);
	}
}
void print(int a[])
{
	if(a[0]==0){
		printf("0");return;
	}
	for(int i=a[0];i>0;i--)
	    printf("%d",a[i]);
	printf("\n");
}


int main()
{
	init(a);
	init(b);
	chugao(a,b);
	printf("%lld\n",c);
	print(a);//余数 
	return 0;
}

改进与思考

*上段代码中的c是用long long进行存储的,但是如果c的值使用任何数据范围都不能表示是,还是只能使用int数组c来表示这个商的值。

先看一本通书上的参考代码:

100分代码参考

#include<iostream>
#include<cstring>
using namespace std;
int a[500],b[500],c[500],d,i;

void init(int a[])
{string s;
cin>>s;//读入字符串 
a[0]=s.length();//用a[0] 计算字符串s的位数 
for(i=1;i<=a[0];i++)
a[i]=s[a[0]-i]-'0';//将数串s转换成数组a,并倒序存储 
}

 void print(int a[])//打印输出 
 {int i;
 if(a[0]==0) {cout<<0<<endl;return;//字符长度为0,输出0 
 }
 for(i=a[0];i>=1;i--) cout<<a[i];//倒序输出 
 cout<<endl;
 return;
 } 
 
  int compare(int a[],int b[])//比较ab的大小关系,如果a大于b为1,a小于b为-1,a等于b为0 
 	{int i;
	 if(a[0]>b[0]) return 1; 
	 if(a[0]<b[0]) return -1;
	 for(i=a[0];i>0;i--) {   //从高位到低位进行比较 
	 	if(a[i]>b[i]) return 1;
	 	if(a[i]<b[i]) return -1;
	 }
	 return 0;
 }


void jian(int a[],int b[]){//计算a=a-b 
	int flag,i;
	flag=compare(a,b);//调用比较函数判断大小
	if(flag==0) {
		a[0]=0;return;
	} 
	if(flag==1) {
		for(i=1;i<=a[0];i++){
			if(a[i]<b[i]){
				a[i+1]--;
				a[i]+=10;//不够减则向上借一位 
			}
		a[i]-=b[i]; 
		}
		while(a[0]>0&&a[a[0]]==0) a[0]--;//修正a的位数
		return; 
	}
}

void numcpy(int p[],int q[],int det)//复制p数组到q数组从det开始的地方
{
for(int i=1;i<=p[0];i++) q[i+det-1]=p[i];
q[0]=p[0]+det-1; }


void chugao(int a[],int b[],int c[])
{int i,tmp[101];
c[0]=a[0]-b[0]+1;
for(i=c[0];i>0;i--){
	memset(tmp,0,sizeof(tmp));
	numcpy(b,tmp,i);
	while(compare(a,tmp)>=0){c[i]++;jian(a,tmp);
	}
}
while(c[0]>0&&c[c[0]]==0) c[0]--;
return;
}

int main(){
	memset(a,0,sizeof(a));
	memset(b,0,sizeof(b));
	memset(c,0,sizeof(c));
	init(a);
	init(b);
	chugao(a,b,c);
	print(c);
	print(a);
	return 0;
}

代码解释

栗子:1234-56,1234存在a数组,56存在b数组,将b数组存放在tmp数组中,但是并不是一对一的存放,而是第一次循环,让56存放成5600,比较a和tmp,显然1234<5600,下次又将56存放成560,1234-560=674,这时就能成功存放一个1在c中,而且是对应的c2中,然后发现674-560=114,c2更新为2。114-560<0,因此c2的更新到此结束,应该更新c1,将b56原样复制给tmp,114-56=58,c1=1;58-56=2,c1++更新为2,2-56<0。结束循环。
基于以上的计算,可以将22这个数字分别放在c2和c1中,tmp存在的意义在于不是像第一段代码中的计算到10次的时候循环加到22次,个人自行体会。

第一次写博客,mark一下。菜的不得了~

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值