浮点转定点算法-加法运算

来源:互联网 发布:淘宝客服联系方式 编辑:程序博客网 时间:2024/05/19 18:38

这里默认用的是32位的float存储,其具体规则可以看个连接http://bbs.chinaunix.net/thread-3746530-1-1.html

  1. 将浮点数用32位的定点形式表示。

  2. 将两个数通过移位扩大至相同的倍数。

  3. 定点加法运算。

  4. 将上一步的运算结果还原为浮点表示。

    #define MIN(X,Y) (X>=Y?Y:X)/** 浮点的加法运算转换为定点的加法运算 *  author : zgr 2014-04-03  * 1. 内存中符号位+阶码+尾数的浮点表示法转换为符号位+整数部分+尾数部分的表示法 * 2. 找到合适的Q值,并取较大的Q值,然后通过移位操作转为同一Q值的定标数 * 3. 做定标数的加减运算 * 4. 将定标数的结果根据其Q值,转换为float的表示形式(符号位+阶码+尾数) */float inter_fadd(float x1, float x2){int Q1, Q2, Q;int xq1, xq2, xq;int ipart, exponent1, exponent2, n, index;int effective1, effective2;if(((*(int*)&x1)&0x7f800000)==0x00000000){ //阶码为0,以0计effective1 = 0;ipart = 0;exponent1 = 30;} else if(((*(int*)&x1)&0x7f800000)==0x7f800000){ //放弃非法数值或者无穷大或无穷小的数值return 0.0f;} else {effective1 = ipart = (((*(int*)&x1)&0x7fffff) | 0x800000); //取出有效数字部分 1.XXXXXXXXXXXexponent1 = 150 - ((*(int*)&x1)>>23 & 0xff); //23 - (b-127)//通过移位截断小数部分,保留整数部分if(exponent1 < 0)ipart = ipart << (-exponent1);else if(exponent1>31)ipart = ipart >> 31;elseipart = ipart >> exponent1;}//计算合适的Q值,这里取最长30位存放有效数字,做到最大的精确度,而不溢出for(n=0; n<31; n++){if(ipart < (1<<n)){Q1 = 30 - n;break;}}if(((*(int*)&x2)&0x7f800000)==0x00000000){effective2 = 0;ipart = 0;exponent2 = 30;} else if(((*(int*)&x2)&0x7f800000)==0x7f800000){return 0.0f;} else {effective2 = ipart = (((*(int*)&x2)&0x7fffff) | 0x800000);exponent2 = 150 - ((*(int*)&x2)>>23 & 0xff);if(exponent2 < 0)ipart = ipart << (-exponent2);else if(exponent2>31)ipart = ipart >> 31;elseipart = ipart >> exponent2;}for(n=0; n<31; n++){if(ipart < (1<<n)){Q2 = 30 - n;break;}}//取较小Q值,保证不溢出Q = MIN(Q1, Q2);//通过移位,扩展至同样的倍数if(exponent1>=0 && (exponent1-Q)>=0){xq1 = effective1>>(exponent1-Q);}else{xq1 = effective1<<(Q-exponent1);}if(exponent2>=0 && (exponent2-Q)>=0){xq2 = effective2>>(exponent2-Q);}else{xq2 = effective2<<(Q-exponent2);}//定标运算xq = xq1 + xq2;//找到最高有效位的索引,用于浮点存储n = -1;for(index=0; index<31; index++){if(xq & (1<<index)){n = index;}}if(n == -1) //全为0,则为0.0freturn 0.0f;else{exponent1 = (n-Q) + 127; //计算阶码//保留23位尾数if(n-23>=0){xq = xq>>(n-23);}else{xq = xq<<(23-n);}//保留符号位,拼接阶码与尾数xq = (xq&0x807fffff)|((exponent1&0xff)<<23);return *(float*)&xq;}}

float my_fadd(float x1, float x2){float res;int temp1, temp2;if(!(((*(int*)&x1)&0x80000000)) && !(((*(int*)&x2)&0x80000000))){//if x1>0 && x2>0 then x1+x2res = inter_fadd(x1, x2);}else if((((*(int*)&x1)&0x80000000)) && (((*(int*)&x2)&0x80000000))){//if x1<0 && x2<0 then -(|x1| + |x2|)temp1 = (*(int*)&x1)&0x7fffffff;temp2 = (*(int*)&x2)&0x7fffffff;res = inter_fadd(*(float*)&temp1, *(float*)&temp2);temp1 = (*(int*)&res) ^ 0x80000000; //符号取反res = *(float*)&temp1;}else if(!(((*(int*)&x1)&0x80000000)) && (((*(int*)&x2)&0x80000000))){//if x1>0 && x2<0 then x1 - |x2|temp2 = (*(int*)&x2)&0x7fffffff;res = inter_fminus(x1, *(float*)&temp2);}else if((((*(int*)&x1)&0x80000000)) && !(((*(int*)&x2)&0x80000000))){//if x1<0 && x2>0 then x2 - |x1|temp1 = (*(int*)&x1)&0x7fffffff;res = inter_fminus(x2, *(float*)&temp1);}else{res = 0.0f;}return res;}


0 0
原创粉丝点击