在C ++中实现double sqrt(double x)

时间:2011-02-15 05:13:30

标签: c++ sqrt

在不使用std库的情况下在C ++中实现double sqrt(double x)

这是我在这里看到的Facebook面试问题。 http://www.glassdoor.com/Interview/Implement-double-sqrt-double-x-in-C-QTN_87210.htm 还有其他好主意吗?...

!!!编辑。!!!(不使用std库。)

4 个答案:

答案 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

但它需要先前的“迭代”来计算近似的对数和指数。