高精度4位压缩法原理与实现
2016-01-11 22:18
232 查看
我们都知道 int类型占32bit 可表示范围: [-2147483648,2147483647] long long类型 64bit可表示范围:[-9223372036854775808,9223372036854775807]
int可以完整表达9位数字,long long可以完整表达18位。(完整表达的意思是能表示到该位的任意数字)
当我们想表达到成千上万位的数时,int、long long都不再适合。所以我们便引入高精度的概念。
所谓高精度就是用数组来充当数字的容器。开辟若干个空间,每个单元内存放固定数目的数据。
高精度常用的方法主要有:不压缩法、压缩4位法、和压缩9位的方法。
不压缩法:主要是用char类型开辟的数组,每个元素内存放一位数字。
例如:
2156897546
用普通不压缩方法存储,其数据结构为:
注意:此时数组中存放的是数值并不是ASCll对应的字符!之所以倒序存放是为了便于以后进行运算时溢位的情况。
压缩4位法:用int类型开辟的数组,每个元素内存放四位数字。
ps:为什么是四位呢?因为int类型能完整表达9位以内的任何数字。而存储四位数字是因为在进行乘法运算时,很可能会存在四位×四位的情况,而其结果不会超过八位。int类型完全可以存储。如果存放四位以上的数字的时候,int不能完整的存放其结果,因而无法正确计算。
例如:
2156897546
用压缩4方法存储,其数据结构为:
特点:自右向左每选取4位存放至数组一个单元内。最后不够的单独放一个空间。(四位内部还是正序的,总体是逆序的)
压缩9位法:与压缩4位法大致相同,区别在于存放的数组是用long long类型开辟的,每个元素内存放9位数字。
例如:
2156897546
用压缩9方法存储,其数据结构为:
三种方式归根结底都是进制的转换问题:普通不压缩法相当于十进制,四位压缩法相当于一万进制,九位压缩法相当于十亿进制。
三种方法的时间效率不同:假设两个数进行四则运算。运用普通法存储拥有最多的单位,其次是四位压缩法,最少是九位压缩法。进行加法运算时,两个数组中,以其中一个数组为起点,使其各个单元与另一个数组的各个单元进行相加运算。其时间复杂度为O(n^2)级。因此压缩9位存储法开辟的单元少,所以消耗的时间最少。
在此我们仅此介绍四位压缩法的构造以及乘法与加法计算样例(有可能的话,以后会补齐其他的四则运算=_=)
int可以完整表达9位数字,long long可以完整表达18位。(完整表达的意思是能表示到该位的任意数字)
当我们想表达到成千上万位的数时,int、long long都不再适合。所以我们便引入高精度的概念。
所谓高精度就是用数组来充当数字的容器。开辟若干个空间,每个单元内存放固定数目的数据。
高精度常用的方法主要有:不压缩法、压缩4位法、和压缩9位的方法。
不压缩法:主要是用char类型开辟的数组,每个元素内存放一位数字。
例如:
2156897546
用普通不压缩方法存储,其数据结构为:
6 | 4 | 5 | 7 | 9 | 8 | 6 | 5 | 1 | 2 |
压缩4位法:用int类型开辟的数组,每个元素内存放四位数字。
ps:为什么是四位呢?因为int类型能完整表达9位以内的任何数字。而存储四位数字是因为在进行乘法运算时,很可能会存在四位×四位的情况,而其结果不会超过八位。int类型完全可以存储。如果存放四位以上的数字的时候,int不能完整的存放其结果,因而无法正确计算。
例如:
2156897546
用压缩4方法存储,其数据结构为:
7546 | 5689 | 21 |
压缩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<j) //循环次数是取len1,和len2中最大的数 { num3[i]+=num1[i]+num2[i];//相加 if(num3[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<len1) { k=i; j=0; while(j<len2) { num3[k]+=num1[i]*num2[j]; //本位原来可能有数字,所以用+= if(num3[k]>=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; }
相关文章推荐
- C#使用DeflateStream解压缩数据文件的方法
- C#调用WinRar执行rar、zip压缩的方法
- C#实现页面GZip或Deflate压缩的方法
- C#使用iCSharpcode进行文件压缩实现方法
- C#实现压缩HTML代码的方法
- Asp.net在线备份、压缩和修复Access数据库示例代码
- 使用UglifyJS合并/压缩JavaScript的方法
- 高性能WEB开发 JS、CSS的合并、压缩、缓存管理
- 脚本分析、压缩、混淆工具 JSA新版本发布,压缩效率提高大约10%
- 发布一个高效的JavaScript分析、压缩工具 JavaScript Analyser
- PHP实现图片压缩的两则实例
- 在IIS上启用Gzip压缩 (HTTP压缩)第1/3页
- javascript实现的样式表(CSS) 格式整理与压缩
- php zlib压缩和解压缩swf文件的代码
- YUI Compressor压缩JavaScript原理及微优化
- Nginx中的Gzip压缩配置介绍
- python zip文件 压缩
- Tomcat配置gzip压缩提高浏览网站的速度
- C#实现的文件压缩和解压缩类
- CSS代码格式化和压缩的方法与技巧