Implement double sqrt(double x) in C++ [closed]

谁都会走 提交于 2020-01-01 20:02:11

问题


Implement double sqrt(double x) in C++ without using std library.

This is a facebook interview question I saw here. http://www.glassdoor.com/Interview/Implement-double-sqrt-double-x-in-C-QTN_87210.htm Any other good idea about this?...

!!!Edited.!!!(without using std library.)


回答1:


Look here. This CodeProject article compares 14 different methods for computing the square root.




回答2:


The two obvious answers are bisection (semi-slow) and Newton-Raphson/Leibniz iteration (usually faster). To keep from spoiling anybody's fun, I'll do a reinterpret_cast on the question -- here's an implementation of an integer square root in 8086 assembly language using the Newton-Raphson technique:

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

This is open to some improvement -- it uses x/2 as its initial guess at the sqrt(x). With 386+ instructions, you can use bsr to find the most significant bit that's set to get a rough approximation of log2x, and divide that by 2 to get your initial approximation.

OTOH, this really only made sense on ancient processors. For anything since the 486 (or so) that has built-in floating point hardware, it's nearly certain that the FSQRT instruction will beat this (or pretty much anything else you can write).




回答3:


Here is one of the most genius sqrt implementations which can be found on wikipedia. It is not the most accurate, but extremely fast.

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;
}



回答4:


If I am allowed to use log (ln) and exp then of course exp(log(x)/2) will give me the square root.

Assuming not:

If our value we find the sqrt of is x and the start value is y then we iterate y->(y+x/y)/2

Terminating condition would either be a proximity of y to its previous value or of y*y to x.

With 385 as my x value I get these values in my iterations (Excel)

1
193
97.49740933
50.7231161
29.15667189
21.1805984
19.67880541
19.62150055
19.62141687
19.62141687

You can use an "approximate" 2^(log base 2(x)/2) as a start point instead of 1. 385 has a log somewhere between 8 and 9, so if we say 8.5 and therefore start with 2^4.25. If we do this linear between 16 and 32 then we would start with 20.

Starting with 20 I get there in just 4 steps:

20
19.625
19.6214172
19.62141687

but it required previous "iterations" to calculate the approximate log and exponential.



来源:https://stackoverflow.com/questions/5000109/implement-double-sqrtdouble-x-in-c

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!