在C+中实现双sqrt(双x)+; 在C++中使用双Sqt(double x)< /C> >,不使用STD库。< /P>
这是我在这里看到的一个facebook采访问题。 还有什么好主意吗在C+中实现双sqrt(双x)+; 在C++中使用双Sqt(double x)< /C> >,不使用STD库。< /P>,c++,sqrt,C++,Sqrt,这是我在这里看到的一个facebook采访问题。 还有什么好主意吗 !!!编辑。!!!(不使用std库。)这里是可以在上找到的最优秀的genius sqrt实现之一。这不是最准确的,但速度非常快 float fast_sqrt(float number) { long i; float x2, y; const float threehalfs = 1.5F; x2 = number * 0.5F; y = number; i = * ( long *
!!!编辑。!!!(不使用std库。)这里是可以在上找到的最优秀的genius sqrt实现之一。这不是最准确的,但速度非常快
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;
}
两个明显的答案是对分(半慢)和牛顿-拉斐逊/莱布尼兹迭代(通常更快)。为了不破坏任何人的乐趣,我将重新解释这个问题——下面是8086汇编语言中使用Newton Raphson技术实现的整数平方根:
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
查找设置为获得log2x粗略近似值的最高有效位,并将其除以2以获得初始近似值
OTOH,这只有在古代处理器上才有意义。自从486(或更多)内置浮点硬件以来,几乎可以肯定的是,
FSQRT
指令将击败这条指令(或几乎任何您可以编写的指令)。看。这篇CodeProject文章比较了计算平方根的14种不同方法。如果允许我使用log(ln)和exp,那么exp(log(x)/2)当然会给出平方根
假设不是:
如果我们的值是x的sqrt,开始值是y,那么我们迭代y->(y+x/y)/2
终止条件可能是y接近其先前值,或者是y*y接近x
以385作为我的x值,我在迭代(Excel)中获得这些值
您可以使用“近似”2^(对数基数2(x)/2)作为起点,而不是1。
385的日志在8到9之间,所以如果我们说8.5,那么从2^4.25开始。如果我们在16和32之间做线性,那么我们将从20开始
从20开始,我只需4个步骤即可实现:
20
19.625
19.6214172
19.62141687
但是它需要以前的“迭代”来计算近似的对数和指数。
#include
[newline]double-sqrt(double-x){return-std::sqrt(x);}
@James:I在想include
[newline]double-sqrt(double-x){return std::pow(x,0.5)}
这肯定是最愚蠢的面试问题之一。他们想要一个有C++能力的人或者有人知道算法,这很容易被查到吗?你的意思是告诉我们你认为面试应该是什么?他想要这份工作吗?你应该试着在面试中给他们留下深刻印象。@Tony:“我会使用来自Quake的快速平方根逆函数的方法——这个公式太神奇了——你知道它是不是?”可能就足够了。(虽然从技术上讲,这做了3次牛顿-拉斐逊近似,而不是1次…所以这不完全是同一件事)哦,是的,我添加了这些以获得更高的精度,但忘了将它们去掉。基本上和tho一样。@regality:我对整数使用了这种方法,对于32位,一次迭代就足以达到100%的精度(随机数和包括边),您是否检查了float
的额外迭代?据我所知,使用倒数方法更快,可能是因为它用聪明的黑客代替了循环。但是我不确定它的精度。@Matthieu M:是的,如果你改变这个问题,你可以稍微提高速度。他们中的大多数人也做了一个非常粗糙的近似,仅适用于大约10或12位(在典型分辨率下仍然是~1像素)。然而,对于一个实际的平方根来说,它真的很难打败专用硬件。是的,很明显,但我指的是你写的汇编函数:)我使用了对整数具有完美精度的倒数方法,我猜添加一些牛顿迭代会在某种程度上提高精度。有趣的是得到了一个很好的一次近似值,然后可以根据需要改进精度。
20
19.625
19.6214172
19.62141687