我正在一个项目中工作,我需要计算一个16位数的平方根。我使用的NXP微控制器并不支持浮点运算。在线查看我发现了以下方法Fixed-Point Square Root by Ken Turkowsky from Apple。我还发现了相同的算法,并对WEB进行了一些修改,包括:Looking for an efficient integer square root algorithm for ARM Thumb2 我在这里复制代码,以便在链接断开时使其可用:
void put_space(unsigned int number)
{
int i;
char spaces = 12;
char buffer[15];
char number_of_chars = sprintf(buffer,"%u",number);
for(i=0;i<spaces-number_of_chars;i++)
{
printf(" ");
}
}
void print_binary(unsigned int number)
{
int i;
unsigned char bit;
for(i=0;i<32;i++)
{
if(i%8 == 0 && i!=0)
{
printf(" ");
}
bit = (number & (2147483648 >> i)) == (2147483648 >> i);
printf("%u",bit);
}
}
void print_number(unsigned int number)
{
print_binary(number);
printf(" ");
printf("(%u)",number);
put_space(number);
}
typedef signed int TFract; /* 2 integer bits, 30 fractional bits */
TFract FFracSqrt(TFract x)
{
register unsigned int root, remHi, remLo, testDiv, count;
root = 0; /* Clear root */ printf("root: "); print_number(root);
remHi = 0; /* Clear high part of partial remainder */ printf("remHi: "); print_number(remHi);
remLo = x; /* Get argument into low part of partial remainder */ printf("remLo: "); print_number(remLo);
count = 30; /* Load loop counter */
printf("\n\n");
do
{
remHi = (remHi<<2) | (remLo>>30); printf("remHi: "); print_number(remHi);
remLo <<= 2; /* get 2 bits of arg */ printf("remLo: "); print_number(remLo);
root <<= 1; /* Get ready for the next bit in the root */ printf("root: "); print_number(root);
testDiv = (root << 1) + 1; /* Test radical */ printf("testDiv: "); print_number(testDiv);
if (remHi >= testDiv)
{
remHi -= testDiv; printf("remHi: "); print_number(remHi);
root++; printf("root: "); print_number(root);
}
printf("\n");
} while (count-- != 0);
printf("\n\nResult: %u\n\n",root);
return(root);
}
我可以理解算法中发生了什么,包括移位和OR操作。但是,我无法理解这段代码背后的数学。 FFracSqrt收到一个&#34; x&#34;整数作为参数并返回楼层(sqrt(x)* 32768)。这是怎么发生的? 请帮助我和其他人理解它,因为到目前为止我还没有找到关于这个理论的任何信息。 此致,
我在这里输入输入为2时的输出:
在do-while循环之前
root:00000000 00000000 00000000 00000000(0)
remHi:00000000 00000000 00000000 00000000(0)
remLo:00000000 00000000 00000000 00000010(2)
进入do-while循环
remHi:00000000 00000000 00000000 00000000(0)
remLo:00000000 00000000 00000000 00001000(8)
root:00000000 00000000 00000000 00000000(0)
testDiv:00000000 00000000 00000000 00000001(1)
remHi:00000000 00000000 00000000 00000000(0)
remLo:00000000 00000000 00000000 00100000(32)
root:00000000 00000000 00000000 00000000(0)
testDiv:00000000 00000000 00000000 00000001(1)
remHi:00000000 00000000 00000000 00000000(0)
remLo:00000000 00000000 00000000 10000000(128)
root:00000000 00000000 00000000 00000000(0)
testDiv:00000000 00000000 00000000 00000001(1)
remHi:00000000 00000000 00000000 00000000(0)
remLo:00000000 00000000 00000010 00000000(512)
root:00000000 00000000 00000000 00000000(0)
testDiv:00000000 00000000 00000000 00000001(1)
remHi:00000000 00000000 00000000 00000000(0)
remLo:00000000 00000000 00001000 00000000(2048)
root:00000000 00000000 00000000 00000000(0)
testDiv:00000000 00000000 00000000 00000001(1)
remHi:00000000 00000000 00000000 00000000(0)
remLo:00000000 00000000 00100000 00000000(8192)
root:00000000 00000000 00000000 00000000(0)
testDiv:00000000 00000000 00000000 00000001(1)
remHi:00000000 00000000 00000000 00000000(0)
remLo:00000000 00000000 10000000 00000000(32768)
root:00000000 00000000 00000000 00000000(0)
testDiv:00000000 00000000 00000000 00000001(1)
remHi:00000000 00000000 00000000 00000000(0)
remLo:00000000 00000010 00000000 00000000(131072)
root:00000000 00000000 00000000 00000000(0)
testDiv:00000000 00000000 00000000 00000001(1)
remHi:00000000 00000000 00000000 00000000(0)
remLo:00000000 00001000 00000000 00000000(524288)
root:00000000 00000000 00000000 00000000(0)
testDiv:00000000 00000000 00000000 00000001(1)
remHi:00000000 00000000 00000000 00000000(0)
remLo:00000000 00100000 00000000 00000000(2097152)
root:00000000 00000000 00000000 00000000(0)
testDiv:00000000 00000000 00000000 00000001(1)
remHi:00000000 00000000 00000000 00000000(0)
remLo:00000000 10000000 00000000 00000000(8388608)
root:00000000 00000000 00000000 00000000(0)
testDiv:00000000 00000000 00000000 00000001(1)
remHi:00000000 00000000 00000000 00000000(0)
remLo:00000010 00000000 00000000 00000000(33554432)
root:00000000 00000000 00000000 00000000(0)
testDiv:00000000 00000000 00000000 00000001(1)
remHi:00000000 00000000 00000000 00000000(0)
remLo:00001000 00000000 00000000 00000000(134217728)
root:00000000 00000000 00000000 00000000(0)
testDiv:00000000 00000000 00000000 00000001(1)
remHi:00000000 00000000 00000000 00000000(0)
remLo:00100000 00000000 00000000 00000000(536870912)
root:00000000 00000000 00000000 00000000(0)
testDiv:00000000 00000000 00000000 00000001(1)
remHi:00000000 00000000 00000000 00000000(0)
remLo:10000000 00000000 00000000 00000000(2147483648)
root:00000000 00000000 00000000 00000000(0)
testDiv:00000000 00000000 00000000 00000001(1)
remHi:00000000 00000000 00000000 00000010(2)
remLo:00000000 00000000 00000000 00000000(0)
root:00000000 00000000 00000000 00000000(0)
testDiv:00000000 00000000 00000000 00000001(1)
如果条件为TRUE
remHi:00000000 00000000 00000000 00000001(1)
root:00000000 00000000 00000000 00000001(1)
remHi:00000000 00000000 00000000 00000100(4)
remLo:00000000 00000000 00000000 00000000(0)
root:00000000 00000000 00000000 00000010(2)
testDiv:00000000 00000000 00000000 00000101(5)
remHi:00000000 00000000 00000000 00010000(16)
remLo:00000000 00000000 00000000 00000000(0)
root:00000000 00000000 00000000 00000100(4)
testDiv:00000000 00000000 00000000 00001001(9)
如果条件为TRUE
remHi:00000000 00000000 00000000 00000111(7)
root:00000000 00000000 00000000 00000101(5)
remHi:00000000 00000000 00000000 00011100(28)
remLo:00000000 00000000 00000000 00000000(0)
root:00000000 00000000 00000000 00001010(10)
testDiv:00000000 00000000 00000000 00010101(21)
如果条件为TRUE
remHi:00000000 00000000 00000000 00000111(7)
root:00000000 00000000 00000000 00001011(11)
remHi:00000000 00000000 00000000 00011100(28)
remLo:00000000 00000000 00000000 00000000(0)
root:00000000 00000000 00000000 00010110(22)
testDiv:00000000 00000000 00000000 00101101(45)
remHi:00000000 00000000 00000000 01110000(112)
remLo:00000000 00000000 00000000 00000000(0)
root:00000000 00000000 00000000 00101100(44)
testDiv:00000000 00000000 00000000 01011001(89)
如果条件为TRUE
remHi:00000000 00000000 00000000 00010111(23)
root:00000000 00000000 00000000 00101101(45)
remHi:00000000 00000000 00000000 01011100(92)
remLo:00000000 00000000 00000000 00000000(0)
root:00000000 00000000 00000000 01011010(90)
testDiv:00000000 00000000 00000000 10110101(181)
remHi:00000000 00000000 00000001 01110000(368)
remLo:00000000 00000000 00000000 00000000(0)
root:00000000 00000000 00000000 10110100(180)
testDiv:00000000 00000000 00000001 01101001(361)
如果条件为TRUE
remHi:00000000 00000000 00000000 00000111(7)
root:00000000 00000000 00000000 10110101(181)
remHi:00000000 00000000 00000000 00011100(28)
remLo:00000000 00000000 00000000 00000000(0)
root:00000000 00000000 00000001 01101010(362)
testDiv:00000000 00000000 00000010 11010101(725)
remHi:00000000 00000000 00000000 01110000(112)
remLo:00000000 00000000 00000000 00000000(0)
root:00000000 00000000 00000010 11010100(724)
testDiv:00000000 00000000 00000101 10101001(1449)
remHi:00000000 00000000 00000001 11000000(448)
remLo:00000000 00000000 00000000 00000000(0)
root:00000000 00000000 00000101 10101000(1448)
testDiv:00000000 00000000 00001011 01010001(2897)
remHi:00000000 00000000 00000111 00000000(1792)
remLo:00000000 00000000 00000000 00000000(0)
root:00000000 00000000 00001011 01010000(2896)
testDiv:00000000 00000000 00010110 10100001(5793)
remHi:00000000 00000000 00011100 00000000(7168)
remLo:00000000 00000000 00000000 00000000(0)
root:00000000 00000000 00010110 10100000(5792)
testDiv:00000000 00000000 00101101 01000001(11585)
remHi:00000000 00000000 01110000 00000000(28672)
remLo:00000000 00000000 00000000 00000000(0)
root:00000000 00000000 00101101 01000000(11584)
testDiv:00000000 00000000 01011010 10000001(23169)
如果条件为TRUE
remHi:00000000 00000000 00010101 01111111(5503)
root:00000000 00000000 00101101 01000001(11585)
remHi:00000000 00000000 01010101 11111100(22012)
remLo:00000000 00000000 00000000 00000000(0)
root:00000000 00000000 01011010 10000010(23170)
testDiv:00000000 00000000 10110101 00000101(46341)
remHi:00000000 00000001 01010111 11110000(88048)
remLo:00000000 00000000 00000000 00000000(0)
root:00000000 00000000 10110101 00000100(46340)
testDiv:00000000 00000001 01101010 00001001(92681)
结果:46340
答案 0 :(得分:1)
这是我的评论尝试
TFract FFracSqrt(TFract x)
{
unsigned root = 0; /* Clear root */
//remHi & remLo forming a 64bit unsigned integer
//remHiLo containing the remainder from the radicant not yet transfered into root
unsigned remHi = 0;
unsigned remLo = x;
unsigned bitcount = 30; /* Load loop counter */
do
{
//shift left the remHiLo package by two bit positions
remHi = (remHi<<2) | (remLo>>30);
remLo <<= 2;
//As we multiplied remHiLo with 4, it is fair to multiply the root with sqrt(4)
root <<= 1;
//We just shifted in a zero bit in root. Should it be set?
//We should check whether (root+1) is too large
//(root+1) * (root+1)
//root^2 + 2*root + 1
//We always deduct root^2 from remHi, so we need to check only the delta
//between root^2 and (root+1)^2
unsigned testDiv = (root << 1) + 1;
if (remHi < testDiv)
{
//root+1 would overshoot the radicant, so leave everything as it is
}
else
{
root++; //set LSB
remHi -= testDiv; //update remHi to reflect the new bit in root
}
} while (bitcount-- != 0);
return root;