以下为快速开放算法的实现,运用在我的实际项目中,我琢磨出来的一种快速开方算法,我项目中使用的是32位数的快速开方算法,并用VB验证过结果,单片机由于资源有限,当实际中遇到16位,8位的开方运算,可以增加速度。如32位开方,只建立2^14的表(根据精度来确定表的大小),16位开方我一般用2^6的表就可以实现,实现的方法就是大数字甩尾,小数字开方保留。
开方快速算法的实现:
为保证计算结果的精度选择方法一。
方法一:在Rom比较充足的情况下做查表,粗算加精算的快速算法做32位数的开方
const unsigned int sqrt_32[16384]={ 0, 256, 362, 443, 512, 572, 627, 677, 724, 768,。。。。};
建立一个表0~0x3fff数字的开方记做sqrt_32=√a (a=0~0x3fff)*256,扩大256倍,最后一个字节表示小数点后的数,然后根据√b=2n×(√b)/22n,用单片机做就是
long temp0;
unsigned long kaifang(unsigned long ss){
uint8 dat_count,count;
long temp1;
uint8 i;
i=17;
dat_count=0;
temp1=ss>>14;
do{
if((temp1&0x3ffff)!=0x0000){//判断被开方数的最18位是否是1,是1就做右移操作,
//但是必须保证是2的偶数次,当判到有效位小于等于14位的时候进行查表,结束后
//在向右移n位乘回来,可以根据自己要求的精度来建表。
ss>>=1;
temp1>>=1;
dat_count++;
}
else {
if(dat_count%2==0){
break;
}
else{
ss>>=1;
dat_count++;
}
}
}while(i-->0);
temp0=sqrt_32[ss];
count=dat_count/2;
for(uint8 j=0;j<count;j++){
temp0<<=1;
}
return temp0;
}
该方法在单片机中使用可以大大加快程序的速度,还可以保证在比较高的精度上,缺点太耗rom了。
方法2:在程序rom比较小,但是对精度要求不高的场合可以使用
unsigned int sqrt_16(unsigned long dat){
unsigned int NN, i;
unsigned long tmp, ttp; // 结果、循环计数
if (dat == 0) // 被开方数,开方结果也为0
return 0;
NN = 0;
tmp = (dat >> 30); // 获取最高位:B[m-1]
dat <<= 2;
if (tmp > 1) { // 最高位为1
NN ++; // 结果当前位为1,否则为默认的0
tmp -= NN;
}
for (i=15; i>0; i--) { // 求剩余的15位
NN <<= 1; // 左移一位
tmp <<= 2;
tmp += (dat >> 30); // 假设
ttp = NN;
ttp = (ttp<<1)+1;
dat <<= 2;
//////////////////////////////////版权所有,如需转载注明出处 鱼香茄子/////////////////////////////////////////////
用户1268471 2014-10-18 13:55