高精度入门

算法初步入门—简单数学之高精度整数运算

前言: 作为一个蒟蒻,才刚刷题刷到高精度运算,花了半天的时间去理解消化并实践了下这点儿刚学的知识,而晚上打牌又连跪二十把,于是化悲愤为力量,写篇文章来梳理下白天学到的东西(现在才明白知识结构化的重要,会不会太晚,汗颜),第一次写博客,希望各路巨佬可以多多指教,不足之处很多,多多见谅。

高精度整数简介

那么,我们先来了解下什么是高精度整数。

高精度整数,听起来好像什么很高大上的东东,but,它其实也有另一个土名----大整数
以我们c++中基本的数据类型来说,int型的数据范围才为 -2147483648~2147483647([−2^31, 2^31−1]),而long long的数据范围为-9223372036854775808~9223372036854775807([−2^63, 2^63−1]),其实对于大多数情况,这些数据范围已经够用了,

but,我们现在也算是大数据时代,对于一些情况这些基本数据类型不足以存放我们的大整数,那该怎么办了,不急,我们一步一步来介绍。

高精度整数的存储

高精度整数的存储很简单,可以用我们最常用的数组,用数组来存放我们的高精度整数的每一位,即整数的高位存储在数组的高位,整数的低位存储在数组的低位。在具体应用中,为了方便随时调取高精度整数长度,我们一般会开一个结构体:

struct bign{
	int d[10000];    //存放高精度整数的数组,暂开10000个空间,视具体情况而定
	int len;		//高精度整数长度
	bign()
	{
		len=0;
		fill(d,d+10000,0);  //将数组所有元素初始化为0
		//memset(d,0,sizeof(d));也是可以的
	}
};

而输入高精度整数时,我们一般先用字符串读入,在把字符串另存为至bign结构体,给予bign结构体一个也相当于初始化的过程:

//初始化,将接收输入的str数组反转,逆向保存至bign结构体中,
//高精度元素低位存至结构体低位,依次后推
//因为接收输入的字符串数组中,高精度整数的高位存在字符数组低位,
//所以存到bign结构体时需要反转
bign init(char str[])
{
	bign a;
	a.len=strlen(str);            //两种数组的长度相同 
	for(int i=0;i<a.len;i++)
	{
		a.d[i]=str[a.len-1-i]-'0';  //将str数组逆序赋值给结构体bign中的数组 
	}
	return a; 
}

高精度整数的四则运算

这四则运算说实话没有什么逻辑难度,其实就是模拟我们小学学习的加减乘除过程,都是四则运算的基本原理,只不过是用程序来把过程造出来罢了。

高精度整数加法

举个简单例子
89+21
先从最小位相加
9+1=10
对10余数为0,和的个位a[0]=0,十位进10/10=1,
8+2+1=11
对10余数为1,和的十位a[1]=1,百位进11/10=1,
0+1=1
a[2]=1;结束
a[0 ~ 2]=0,1,1; a[2~1]=1,1,0;
89+21=110;

bign add(bign a,bign b)
{
	bign c;         //开一个c来存放相加完的数组
	int len;
	if(a.len>=b.len)     //选择最长的数组来作为接下来相加循环的最大值 
	len=a.len;
	else
	len=b.len;
	int carry=0;  //代表进位数 
	for(int i=0;i<len;i++)
	{
		int t=carry+a.d[i]+b.d[i];
		if(t>=10) carry=t/10;     //更新进位数 
		c.d[i]=t%10;				
	}
	if(carry!=0)			//判断两数相加是否得到更高的位数 
	{						//若有,则开辟更高的数组来存放最高位 
		c.d[len]=carry;
		c.len=len+1;
	}
	else
	{
		c.len=len;
	}
	return c;
}

高精度整数减法

原理同加法,也是模拟我们普通的减法过程

bign sub(bign a,bign b)
{
	bign c;
	int len;
	if(a.len>=b.len)
	len=a.len;
	else
	len=b.len;
	for(int i=0;i<len;i++)
	{
		if(a.d[i]<b.d[i])				
		{
			a.d[i+1]--;						//若相同位数被减数小于减数,则向高位借1 
			c.d[i]=a.d[i]+10-b.d[i];		//同时借的1,由于高一位,所以  ×10 加到被减数 
		}
		else
		{
			c.d[i]=a.d[i]-b.d[i];
		}
	}
	c.len=len; 
	while(c.len-1>=1&&c.d[c.len-1]==0)   //因为减法所得数位数范围为1-len,所以直接循环判断 
	{
		c.len--;
	}
	return c;
}

高精度整数乘法(高精度乘低精度)

举个栗子
12*12=124
+0 1 2
×0 1 2

+0 2 4
+1 2 0

+1 4 4

bign multiply(bign a,int b) 	//高精度数乘低精度
{							//(能用基本数据类型存储的数据,本代码以int型展开)
	bign c;
	int carry=0;
	for(int i=0;i<a.len;i++)
	{
		int t;
		t=carry+a.d[i]*b;
		carry=t/10;
		c.d[i]=t%10;
	}
	c.len=a.len;
	while(carry!=0)		//和减法一样,相乘结果进位数不确定有几位,可能不止一位,while循环 
	{
		c.d[c.len++]=carry%10;
		carry/=10;
	}
	return c;
}

高精度整数除法(高精度除以低精度)

还是正常的模拟除以过程啦,可以边看代码边在草稿纸上自己计算一下啦,过程很重要

bign divide(bign a,int b)			
{
	bign c;
	int len=a.len;
	int carry=0;
	for(int i=len-1;i>=0;i--)
	{
		int t=carry*10+a.d[i];   //暂存 
		if(t>=b)
		{
			c.d[i]=t/b;   //模拟我们正常的除法计算 
			carry=t%b;		//余数就交给我们低一位数,如此循环 
		}
		else
		{
			c.d[i]=0;
			carry=t;
		}
	}
	c.len=a.len;
	while(c.d[c.len-1]==0&&c.len-1>0)
	{
		c.len--;
	}
	return c;
}

程序就是一个动手玩儿的过程,脑过千遍不如手过一遍,望大家一起加油,努力进步,如果有什么错误请私信我,毕竟是小蒟蒻。

参考书籍:《算法笔记》

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值