高精度之乘除法

高精度篇————
乘除法

咳咳,最近一直在研究该怎么讲接下来的高精度
先说另一件事
家长的一位朋友说,高精度加法可以改进
如果在化字符为数字时把加法做了
可以省三个10000的一维数组
因此我把改进后的代码也奉上

#include <iostream>
#include <math.h>
using namespace std;
string add(string s1,string s2)
{
	string ans="";
	bool f=false;
	int i,l=max(s1.size(),s2.size());
	while(s1.size()<l)  s1='0'+s1;
	while(s2.size()<l)  s2='0'+s2;
	for(i=l-1;i>=0;i--)
	{
        int x1,x2,xs;
        x1=int(s1[i]-'0');
        x2=int(s2[i]-'0');
        xs=x1+x2;
        if(f)  xs++;
        f=false;
        if(xs>9)  f=true;
        xs%=10;
        ans=char(xs+'0')+ans;
    }
    if(f)  ans='1'+ans;
	return ans;
}
int main()
{
    string v1,v2;
    cin>>v1>>v2;
    cout<<add(v1,v2)<<endl;
    return 0;
}

也请大家多多给我纠错以及评论
我会努力改进的

当然,刚才说了那么多,都是为了引出今天的主题
刚才的方法看似省去了空间,但在乘法上可就不行喽~

目录
1.乘法思想
2.乘法实现
3.插曲(一会你就知道了)
4.除法思想
5.除法实现

1.乘法思想
和加减法一样,用数组存起来,再做运算
但是注意,这里要用1个双重循环
因为拿一位去乘字符串,不仅耗时间,也耗空间
因此我们采用一位一位单个去乘
这时,双重循环就能体现出它的作用了
因为在做乘法时,十位及以上要空格
比如1234,做第二个123时会空一个格
这时就可以用双重循环实现

2.乘法实现
实在不方便打字,具体看注释吧

#include<iostream>
#include<cmath>
using namespace std;
string mul(string s1,string s2)
{
	int i,j,a[10005]={0},b[10005]={0},s[10005]={0},w=0,l1=s1.size(),l2=s2.size(),l=max(l1,l2);//定义 
	string ans="";
	for(i=0;i<l1;i++)  a[l1-i-1]=int(s1[i]-'0');//存数组,看过加减法的都明白 
	for(i=0;i<l2;i++)  b[l2-i-1]=int(s2[i]-'0');
	for(i=0;i<l1;i++)//开始双重循环做乘法 
	  for(j=0;j<l2;j++)//第i位可以看成10的i-1次方,存数组前挪了一位,因此根据幂的加法就是s[i+j] 
	    s[i+j]+=a[i]*b[j];
	for(i=0;i<2*l;i++)//和加法一样,整理 
	{
		s[i+1]+=s[i]/10;
		s[i]%=10;
		if(s[i]!=0)  w=i;
	}
	for(i=0;i<=w;i++)  ans=char(s[i]+'0')+ans;//返回为字符串 
	return ans;
}
int main()
{
	string v1,v2;
	cin>>v1>>v2;
	cout<<mul(v1,v2)<<endl;
	return 0;
}

其实大体上和加法差不多,但是要理解其中的方法

3.插曲
这就要牵扯到开头讲的方法
你要是用正在乘的时候整理
你会发现——
痛不欲生!
因为这种方法只能算一次,而乘法涉及多位数
因此不可以省空间
那么,除法可不可以呢?
我的回答很肯定:不行!

4.除法思想
首先,除法与前三个算法都不一样
比如光看竖式
就会发现除法是个异类
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
因此,不能使用正常的算法
那么引入一种新的思想

来分析一下除法的思想:
一是上面的竖式
二是_中有几个_

第一肯定可以,但是很难模拟
于是用第二种方法实现
5.除法实现
详细看注释

#include<iostream>
#include<cmath>
using namespace std;

bool str_Judge_size(string s1,string s2)//判断s1和s2的大小 
{
	if(s1.size()>s2.size()||(s1.size()==s2.size()&&s1>=s2))  return true;//如果s1位数大 
	return false;//或两数位数相同且s1大返回正,否则返回负 
}

string sub(string s1,string s2)//高精度减法就不用再说了吧^_^ 
{
	int i,a[10005]={0},b[10005]={0},s[10005]={0},l1=s1.size(),l2=s2.size(),l=max(l1,l2),w=0;
	string ans="";
	for(i=0;i<l1;i++)  a[l1-i-1]=int(s1[i]-'0');
	for(i=0;i<l2;i++)  b[l2-i-1]=int(s2[i]-'0');
	for(i=0;i<l;i++)  s[i]=a[i]-b[i];
	for(i=0;i<=l;i++)
	{
		if(s[i]<0)
		{
			s[i+1]--;
			s[i]+=10;
		}
		if(s[i]!=0)  w=i;
	}
	for(i=0;i<=w;i++)  ans=char(s[i]+'0')+ans;
	return ans;
}

string div(string s1,string s2)//做除法的两个高精度数 
{
	int s[10005]={0};//s是最终的商,每一个s表示一位数 
	int l1=s1.size(),l2=s2.size();//两个字符串的长度 
	int w=0;//表示商的最高位 
	string ans="",v1=s1,v2;//v1和v2做差 
	while(str_Judge_size(v1,s2))//当商s2比v1大时,即还能减 
	{
		int x=0;//减数扩的倍数 
		v2=s2;
		while(str_Judge_size(v1,v2+"0"))//还可以扩倍 
		{
			v2+='0';//相减的数如果能再大一位,就*10,即在字符串末尾添加‘0 ’ 
			x++;//位数++ 
		}
		v1=sub(v1,v2);//二数相减 
		s[x]++;//s位++ 
        if(x>w)  w=x;//如果位数大于x,x替换成w 
	}
	for(int i=0;i<=w;i++)  ans=char(s[i]+'0')+ans;//把结果转换回string返回 
	return ans;
}

int main()
{
	string v1,v2;//高精度两数 
	cin>>v1>>v2;//输入 
	cout<<div(v1,v2)<<endl;//输出 
	return 0;
}

感谢大家的支持,下期再见

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值