高精度计算

对string类和对象的操作

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

int main()
{
	string str("123456789");
	cout<<str<<endl;
	return 0;
}

输出:
在这里插入图片描述/

将字符数组转换成整形数组程序
int *Str2Int(char *str)
{
	int i, len =strlen(str);
	int *a=new int[(len+1)*sizeof(int)];
	for(int i=0;i<len;i++) a[i]=str[len-i-1]-'0';
	return a;
}

整数数组的归整运算(将a[k]中的数转换成p进制)

int check(int *a,int n)
{
	int k=0,len=n;
	while(a[len-1]==0&&len>1) len--;
	for(int k=0;k<len;k++)
	{
		if(a[k]>=10)
		{
			a[k+1]=a[k+1]+a[k]/10;
			a[k]=a[k]%10;
		}
	}
	if(a[k]!=0) len=k+1; //确定数组最终长度
	return len;
}

归整完毕后,可将整型数组再转换为字符数组,以备后用

char *Int2Str(int *a,int n)
{
	int i;
	char *str=new char[(n+1)*sizeof(char)];
	for(int i=0;i<n;i++) str[i]=(char)a[n-i-1]+48; // a转换为字符数组str
	str[n]='\0';
	return str;
}

高精度四则运算的基本处理方法

对输入数据的处理:
数据小则直接存,大则用字符串存
接下来处理以下三个基本问题:
①计算结果位数的确定
②进位处理和借位处理
③商和余数额求法
加法
减法
两数A,B的减法处理方法有两种:从低位开始或从高位开始
常用的方法是从低位开始:
①确定差的位数:两数之差的位数不超过较大数的位数
②借位处理:做减法运算时,要先判断是否需要借位,如果需要借位那么从上一位借一个1,当作本位的10,上一位减1,然后本位相减
③负数的处理:如果减数B大于被减数A,那么交换A,B的值转化为被减数大于减数的情况处理
乘法
除法
除法是基于减法的方式,采用试商法。做除法运算时,每次都是用被除数减去商与除数的积,如果所得余数不为零,将其扩大10倍再次作为被除数,继续试除,直至余数为零或达到要求的精度为止。
在具体处理时,也可将除法转化为多位数乘1位数,这个多位数就是被除数。然后相加,在采用逐次减法的方法。
下面列出高精度四则运算的程序,每个程序都独立可用

const int MAXLEN = 1000;
// 加法:输入两个用字符数组表示的长整数m1,m2
// 返回一个字符数组指针,指向m1与m2的和
char *addition(char *m1, char *m2)
{
	int i, len1, len2, len, c=0;
	int * t1, * t2;
	len1=strlen(m1);len2=strlen(m2);
	len=(len1>=len2)?len1:len2;  //定位数
	t1=new int[(len+2)*sizeof(int)];
	t2=new int[(len+2)*sizeof(int)];
	t1=Str2Int(m1);
	t2=Str2Int(m2);
	for(i=len1;i<len+1;i++) t1[i]=0; //缺位前导补零
	for(i=len2;i<len+1;i++) t2[i]=0; //缺位前导补零
	for(i=0;i<len;i++) t1[i]=t1[i]+t2[i]; //加法
	len=check(t1,len); // 归整
	return Int2Str(t1,len); //转化为字符串,返回
}

// 减法:输入两个用字符数组表示的长整数m1,m2
// 返回一个字符数组指针,指向m1与m2的差
char *subtract(char *m1, char *m2)
{
	int i, len1, len2, len, c=0, *t1, *t2, cf=0;
	char *temp, *csub;
	len=strlen(m1);len2=strlen(m2);
	len=(len1>=len2)?len1:len2;   // 定位数
	t1=new int[(len+2)*sizeof(int)];
	t2=new int[(len+2)*sizeof(int)];
	temp=new char[(len+2)*sizeof(char)];
	csub=new char[(len+3)*sizeof(char)];
	if((len>len1)||((len2==len1)&&strcmp(m1,m2)<0)) // 当被减数小于减数时,调整
	{
		strcpy(temp,m1); //将m1复制到temp中
		strcpy(m1,m2);
		strcpy(m2,temp);
		len1=strlen(m1);len2=strlen(m2);
		cf=1;
	}
	t1=Str2Int(m1);t2=Str2Int(m2); // m1,m2分别转化为整型数组t1,t2
	for(i=len1;i<len;i++) t1[i]=0;
	for(i=len2;i<len;i++) t2[i]=0;
	for(i=0;i<len;i++)
	{
		if(t1[i]>=t2[i]) t1[i]=t1[i]-t2[i];
		else   //归整
		{
			t1[i]=t1[i]-t2[i];
			c=(t1[i]*(-1)%10)==0?(t1[i]*(-1)/10):(t1[i]*(-1)/10+1);
			t1[i]=t1[i]+10*c;
			t1[i+1]=t1[i+1]-c;
		}
	}
	int n=i, begin =0;
	while(t1[n-1]==0&&n>1) n--;
	if(cf==1)
	{
		csub[0]='-';
		n++;begin=1;
	}
	for(i=begin;i<n;i++) csub[i]=(char)t1[n-i-1]+48;  // 将t1转化为字符数组csub
	csub[n]='\0';
	return csub;
}

// 乘法:输入两个用字符数组表示的长整数m1,m2
// 返回一个字符数组指针,指向m1与m2的积
char *multiply(char *m1,char *m2)
{
	int i, j, len1, len2, len, c=0, *t1, *t2, *prod;
	len1=strlen(m1);len2=strlen(m2);
	len=len1+len2;  // 定位数
	t1=new int[(len1+1)*sizeof(int)];
	t2=new int[(len2+1)*sizeof(int)];
	prod=new int[(len+1)*sizeof(int)];
	t1=Str2Int(m1);t2=Str2Int(m2);
	for(i=0;i<len+1;i++) prod[i]=0; // 	缺位前导补零
	for(i=0;i<len1;i++)
		for(j=0;j<len2;j++)
			prod[i+j]=prod[i+j]+t1[i]*t2[j];
	len=check(prod,len); //归整
	return Int2Str(prod,len);
}

①高精度数除以高精度数的实现方法如下:

// 高精度数除以高精度数
// 输入两个用字符数组表示的长整数m1,m2
// 输出m1被m2除的商quotient和余数remainder
void divide(char *m1, char *m2, char *remainder, char *quotient) 
{
	int i, j, k, len, *temp;
	int len1=strlen(m1), len2=strlen(m2);
	char *m3;
	if(strcmp(m1,m2)==0)
	{
		quotient[0]='1';
		quotient[1]='\0';
		
		remainder[0]='0';
		remainder[1]='\0';
	}
	else if((len1<len2)||(len1==len2)&&strcmp(m1,m2)<0)
	{
		quotient[0]='0';
		quotient[1]='\0';
		remainder=m1;
	}
	else
	{
		temp=new int[(len2+1)*sizeof(int)];
		len=0;
		for(i=0;i<len1;i++)
		{
			temp[i]=0;
			remainder[len]=m1[i]; 
			remainder[len+1]='\0';
			len=strlen(remainder);
			while((len>len2)||((len==len2)&&(strcmp(remainder,m2)>=0)))
			{   //即remainder>=m2
				m3=new char[(len1+1)*sizeof(char)];
				memset(m3,0,sizeof(m3));
				m3=subtract(remainder,m2);//这里采用了逐次减法
				remainder=m3;
				len=strlen(remainder);
				temp[i]++;
			}
			quotient[i]=temp[i]+'0';
		}
		j=0;
		while((j<len1)&&(quotient[j]=='0'))
			j++;
		for(k=0;k<len1-j;k++)
			quotient[k]=quotient[k+j];
		quotient[len-j]='\0';
		if(remainder[0]=0)
		{
			remainder[0]='0';
			remainder[1]='\0';
		}
	}
}

②高精度数除以低精度数的实现方法如下:
关于delete[]
//new[] 必须配合delete[]使用,有时使用delete了不会报错(例如delete基本类型或者结构体等的数组指针)
string* pStr = new string[9];
delete[] pStr; //delete[]会逐个调用“对象数组”的每个对象的“析构函数”,这里用delete肯定报错(除非“这个类,没有析构函数”)


#define max 1000

// 高精度数除以低精度数
// 一下程序中,num是被除数,p是除数,remainder是余数,quotient是商
void HpDivByShort(string num,int p, int * remainder, string quotient)
{
	int len = num.length(), i, s, *nn;  //字符数据num转化为整型数组nn
	nn = new int[len];
	for(i=0;i<len;i++) nn[i]=num[i]-'0';
	int tmp = 0, rem, tmp_q[max], flag=0;
	i=0;
	while((i<len)&&(tmp<p)) //准备试商
	{
		tmp=tmp*10+nn[i];
		i++;
	}
	i--;  // 商的位置
	s=i;  //最高位置i
	tmp_q[i]=tmp/p; // 试商
	rem= tmp%p; //取余
	tmp=rem; // 准备与num的后续数构成新数
	nn[i]=tmp_q[i];
	while(i<len-1)
	{
		tmp=tmp*10+nn[i+1];
		if(tmp<p)
		{
			tmp_q[i+1]=0;
			nn[i+1]=0;
		}
		else
		{
			rem=tmp%p;
			tmp_q[i+1]=tmp/p;
			nn[i+1]=tmp/p;
			tmp=rem;
		}
		i++;
	}
	*remainder=tmp;
	for(i=0;i<len-s;i++)
	{
		tmp_q[i+s]+='0';
		quotient[i]=tmp_q[i+s];
	}
	quotient[len-s]=0;
	delete[]nn;
	return;
}

Basic remains(计算余数)这题没有用到上面的模板

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值