在不使用std库的情况下在C ++中实现double sqrt(double x)
。
这是我在这里看到的Facebook面试问题。 http://www.glassdoor.com/Interview/Implement-double-sqrt-double-x-in-C-QTN_87210.htm 还有其他好主意吗?...
!!!编辑。!!!(不使用std库。)
答案 0 :(得分:6)
看here。此CodeProject文章比较了14种计算平方根的不同方法。
答案 1 :(得分:4)
两个明显的答案是二分(半慢)和牛顿 - 拉斐逊/莱布尼兹迭代(通常更快)。为了避免破坏任何人的乐趣,我将对问题进行reinterpret_cast - 这是使用Newton-Raphson技术在8086汇编语言中实现整数平方根:
isqrt proc uses di, number:word
;
; uses bx, cx, dx
;
mov di,number
mov ax,255
start_loop:
mov bx,ax
xor dx,dx
mov ax,di
div bx
add ax,bx
shr ax,1
mov cx,ax
sub cx,bx
cmp cx,2
ja start_loop
ret
isqrt endp
这有一些改进 - 它使用x / 2作为sqrt(x)的初始猜测。使用386+指令,您可以使用bsr
找到设置为获得log 2 x的粗略近似值的最高有效位,并将其除以2以得到初始近似值。 / p>
OTOH,这真的只对古代处理器有意义。对于具有内置浮点硬件的486(左右)以来的任何事情,几乎可以肯定FSQRT
指令会超过这个(或者你可以写的其他任何东西)。
答案 2 :(得分:3)
这是最具天才的sqrt实现之一,可以在wikipedia找到。它不是最准确,但速度极快。
float fast_sqrt(float number) {
long i;
float x2, y;
const float threehalfs = 1.5F;
x2 = number * 0.5F;
y = number;
i = * ( long * ) &y; // floating point bit level hacking [sic]
i = 0x5f3759df - ( i >> 1 ); // Newton's approximation
y = * ( float * ) &i;
y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration
y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration
y = y * ( threehalfs - ( x2 * y * y ) ); // 3rd iteration
return 1/y;
}
答案 3 :(得分:0)
如果允许我使用log(ln)和exp,那么当然exp(log(x)/ 2)会给我平方根。
假设没有:
如果我们的值得到sqrt为x且起始值为y则我们迭代y->(y + x / y)/ 2
终止条件可以是y与其先前值的接近度,也可以是y * y与x的接近度。
以385作为我的x值,我在迭代中得到这些值(Excel)
1
193
97.49740933
50.7231161
29.15667189
21.1805984
19.67880541
19.62150055
19.62141687
19.62141687
您可以使用“近似”2 ^(log base 2(x)/ 2)作为起点而不是1。 385有一个8到9之间的日志,所以如果我们说8.5因此从2 ^ 4.25开始。如果我们在16到32之间做这个线性,那么我们将从20开始。
从20开始,我只用了4个步骤就到达那里:
20
19.625
19.6214172
19.62141687
但它需要先前的“迭代”来计算近似的对数和指数。