(Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu)
下面是几个数据存储优化的例子, 也是常见的几个例子,都挺有意思。
可能例子的适用性是有一定限制的, 不过例子汇聚到一起,从数据存储优化思路来分析,还是挺有益处的:
1. 交换两个数字,不使用新增变量和函数
(参考实现代码,仅代表一种实现思路)
void swap(int &a, int &b){
a = a + b;
b = a - b;
a = a - b;
};
这个算法是:
基于数据与求和数据的关联,完成了数据交换。
a =(a+b)-b;
b =(a+b)-a;
适用性上:
适用于两个值相加不溢出的情况;
2. 返回两个中的最大的,不使用条件分支与函数
(参考实现代码,仅代表一种实现思路)
int max(int a, int b){
int sum = a + b;
int sub = a - b;
unsigned int flag = (0x80000000 & (unsigned int)sub) >> 31;
sub = ((-flag) ^ (unsigned int)sub) + flag;
sum += sub;
return sum / 2;
};
这个算法是:基于几个个特点
a. 求和数据与求差数据的关联 (a+b) + |a-b| = 2max(a, b)
b. int数据存储结构上,最高位是符号位,可以取出该符号位用于计算
c. 异或操作:与0异或得到其本身,与1异或取反
d. 正负数互转时时,采用取反+1
3. 基于数据自身取值范围的优化存储
例如图片的大小取值一般都是由大小范围限制的;
可以基于它的范围限制特点,优化存储空间。
如果图片大小取值范围在(0, 65536]范围内,前开后闭:就可以把长宽两个取值压缩到一个4字节(32bit)范围内;
压缩时:
int height = width = 65536;
unsigned int merge = (width - 1) << 16 + (height - 1);
解压时:
int height = merge & 0xFFFF + 1;
int width = (merge >> 16) & 0xFFFF + 1;
当然如果图片大小取之范围(0, 1024]范围的:
可以用更小的空间来压缩width/height;
20bit就可以完成两个值得存储。
4. 无符号数基于取值的7位压缩有效值压缩
在自然界通常碰到的整数数字都不是很大,只有少量的较大数字,但是选用4字节存储的范围却很大。
从二进制上来看,大多数字,高位很多0,第一个有效位1产生的比较靠后,从第一个出现的1开始,可能只有较短的长度就结束了。如果能只存储这较短的有效长度,就可以省掉前面高位取值0的空间。
希望算法可以同时满足大数字与小数字的存储,又能基于数字的范围占用不同的空间大小,7位有效值法就非常适用了。
一个字节8位,使用1位来标示,是否数字存储结束;
首位:
0-标示存储值结束
1-标示还有后续字节存值;
其余7位:
存储数值;
这样解析值的时候,就可以一个字节一个字节读取,发现高位为0时结束;把有效数值位串起来就是数字的值。
从而<2^7=128时,1个字节就存下了;
从而<2^14=16384时,2个字节就存下了;
…
5. ZIGZAG负数优化取值
zigzag负数优化取值的原理是,负数通常会在高位占有较多的带1的值,如果对有效位存储的话,例如上面的7位存值的方式—可以把高位的0占用空间都节省掉:但负数的话却不适用,最高位是1,7位存值方式—通常要存更多字节才能保存完。
那为什么不能把负数映射到正数的区间中,把符号位往后放,这样来大多数出现的负数高位取0的值比较多,来节省空间呢?
zigzag的算法就应运而生了。
zigzag-encode时把符号位存到最后1位:
对于负数时,把取值部分存反码在其余位上。
对于正数时,把取之部分直接放在其余位上。
zigzag-decode时,做逆操作;
经过zigzag处理后,对于负值,在用类似7位存值优化方法,大多数情况下就比较能够节省空间了。
abs(value) < 2^6=64时,1个字节存储(负值时,多存一个-64)
abs(value) < 2^13=8192时,2个字节存储(负值时,多存一个-8192)
…
6. 其它思路
利用数据优化存储的思路还有许多,甚至还包括压缩算法的一些思路,都可以完成数据的存储优化
a. 像是圆属性中的面积与半径,可以互相推倒, 保留其一即可
b. 像是利用单位向量的单位化特点,可以从x/y分量得出z分量
c. 像是把数字从文本形态转到二进制存储,数据格式的变更
d. 像是hex码改用base64压缩后,即能够保留原来可见的特点,又可以节省约1/3的空间
e. 像是为了网络传输,常把文件gzip压缩之后,传输给浏览器,浏览器解压后呈现
等等…
(Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu)