初中时老爷子出过这题让我独立解决。
本身不难,只是(a+b)²=a²+b²+2ab的一个简单应用,很容易找到类似短除法的方法。上大学时我曾重新考虑过这个问题,因为一般的短除法在我看来还是有点麻烦。我首先想到这个“麻烦”主要是十进制造成的,而数学运算本身跟进制无关,所以应该选择一个更“友好”的进制。显然,是二进制。此时每一步只需要决定下一位是0还是1,运算变成极其简单的比大小:计算(二进制表示的)√aₙ…a₁a₀.b₀b₁…1. 以小数点为界,把整数部分(aₓ)和小数部分(bₓ)每两位分成一段段(也可以理解为四进制),每一段有00,01,10,11四个可能。
2. 初始化状态:当前已计算的平方根:S=0当前余数:R=0当然游标:最高位段
3. 计算平方根的下一位(二进制):当余数R<S或R=S且当前段为00时,平方根的下一位是t=0,否则t=1
4. 更新状态:将当前段D(i)拼在余数尾部:R={R,D(i)}如果3的结果t=1,则R=R-{S,01}把t拼在平方根尾部:S={S,t}游标前进至下一段
5. 跳回3开始重复,直至除尽,循环,或达到精度要求。举例:计算√20.25,转为二进制√1 01 00.01整数部分分段:01,01,00,小数部分:01初始:S=0,R=0。第一位:S=R且D=01,有t=1更新:R={R,01}-{S,01}=01-01=0,S=1第二位:S=1>0=R,有t=0更新:R={R,01}=01,S={S,0}=10第三位:S=10>01=R,有t=0更新:R={R,00}=100,S={S,0}=100至此整数部分完成,进入小数部分:第一位小数:S=100=R且D=01,有t=1更新:R={R,01}-{S,01}=0,S={S,1}=100.1至此除尽,所以平方根为100.1,转回十进制即为:√20.25=4.5毕业后从事芯片设计工作时,在GPU运算器设计时再次遇到这个问题。根据ic设计的特性,我采用了查表+泰勒级数插值的快速算法。毕竟,为“人的手”优化还是为“机器的二极管”优化,算法的目标是不同的。