高精度 压四位原理及实现

我们都知道 int类型占32bit 可表示范围: [-21474836482147483647] long long类型 64bit可表示范围:[-92233720368547758089223372036854775807]

int可以完整表达9位数字,long long可以完整表达18位。(完整表达的意思是能表示到该位的任意数字)

当我们想表达到成千上万位的数时,intlong long都不再适合。所以我们便引入高精度的概念。

所谓高精度就是用数组来充当数字的容器。开辟若干个空间,每个单元内存放固定数目的数据。

高精度常用的方法主要有:不压缩法、压缩4位法、和压缩9位的方法。

不压缩法:主要是用char类型开辟的数组,每个元素内存放一位数字。

例如:

2156897546

用普通不压缩方法存储,其数据结构为:

6 4 5 7 9 8 6 5 1 2


注意:此时数组中存放的是数值并不是ASCll对应的字符!之所以倒序存放是为了便于以后进行运算时溢位的情况。

 

压缩4位法:用int类型开辟的数组,每个元素内存放四位数字。

ps:为什么是四位呢?因为int类型能完整表达9位以内的任何数字。而存储四位数字是因为在进行乘法运算时,很可能会存在四位×四位的情况,而其结果不会超过八位。int类型完全可以存储。如果存放四位以上的数字的时候,int不能完整的存放其结果,因而无法正确计算。

例如:

2156897546

用压缩4方法存储,其数据结构为:

7546 5689 21


 特点:自右向左每选取4位存放至数组一个单元内。最后不够的单独放一个空间。(四位内部还是正序的,总体是逆序的)

压缩9位法:与压缩4位法大致相同,区别在于存放的数组是用long long类型开辟的,每个元素内存放9位数字。

例如:

2156897546

用压缩9方法存储,其数据结构为:

156897546 21

三种方式归根结底都是进制的转换问题:普通不压缩法相当于十进制,四位压缩法相当于一万进制,九位压缩法相当于十亿进制。

三种方法的时间效率不同:假设两个数进行四则运算。运用普通法存储拥有最多的单位,其次是四位压缩法,最少是九位压缩法。进行加法运算时,两个数组中,以其中一个数组为起点,使其各个单元与另一个数组的各个单元进行相加运算。其时间复杂度为O(n^2)级。因此压缩9位存储法开辟的单元少,所以消耗的时间最少。


在此我们仅此介绍四位压缩法的构造以及乘法与加法计算样例(有可能的话,以后会补齐其他的四则运算=_=)

int StrToNum(const char str[], int num[])//从字符串的最后一位倒序向,int数组正序方向赋值(int数组是倒序的大数)
{
    int len=strlen(str),i,j=0;
    for(i=len-1;i>2;i-=4)//倒序每4个数字存放一个单位内
    {
        if(i-3>=0)
            num[j++]=(str[i-3]-'0')*1000+(str[i-2]-'0')*100+(str[i-1]-'0')*10+(str[i]-'0');
    }
    if(i==0)//如果剩余1个数字
        num[j++]=str[0]-'0';
    else if(i==1)//剩余2个数字
        num[j++]=(str[0]-'0')*10+(str[1]-'0');
    else if(i==2)//剩余3个数字
        num[j++]=(str[0]-'0')*100+(str[1]-'0')*10+(str[2]-'0');
        while(j>0&&num[j-1]==0)	//j返回num的长度
            j--;
    return j;
}

int Add(int num1[],int num2[],int num3[],int len1,int len2,int& num3_begin)//加法  num1,num2是原始数据的数组,num3用来存放结果
{
	int i=0,j=len1>len2?len1:len2;			//len1,len2分别代表数组num1,num2的长度,num3_begin返回结果中数值开始的下标。
	if(len1==0&&len2==0)		//原始数据是0的情况讨论。  0:num1、num2都是0;   1:num1是0    2:num2是0
		return 0;
	else if(len1==0)
		return 1;
	else if(len2==0)
		return 2;
	else
	{
		while(i=10000)		//若数值大于进制进行进位操作
				num3[i+1]+=num3[i]/10000,num3[i]%=10000;
			i++;
		}
		if(num3[i]==0)//返回结果中数值开始的下标
			num3_begin=i-1;
		else
			num3_begin=i;
	}	return -1;
}
int Multiply(int num1[], int num2[], int num3[], int len1, int len2,int &num3_begin)//乘法    存储在num1,num2中的数是从下标0开始倒序存放的。
{
    int i=0,j=0,k=0;
    if(len1==0||len2==0)		//num1、num2有一方是0
        return 0;
    else
        {
            while(i=10000)
						num3[k+1]+=num3[k]/10000,num3[k]%=10000;
					 k++,j++;
                }
                i++;
            }
        }
        if(num3[k]!=0)		//返回数中最高位不为0的下标
            num3_begin=k;
        else
            num3_begin=k-1;
    return 1;
}



  

你可能感兴趣的:(ACM,ACM,大数,高精度,压四位)