我想知道快速实现pow()的方法,例如这个,是否比快速求解sqrt(x)更快地得到一个整数的平方根。我们知道
sqrt(x) = pow(x, 0.5f)
我无法测试速度,因为我没有找到快速实现sqrt的方法。 我的问题是:快速实现pow(x,0.5f)是否比快速实现sqrt(x)更快?
编辑:我的意思是powf-接受浮点数而非双精度数的pow。(双精度数更具误导性)
我想知道快速实现pow()的方法,例如这个,是否比快速求解sqrt(x)更快地得到一个整数的平方根。我们知道
sqrt(x) = pow(x, 0.5f)
我无法测试速度,因为我没有找到快速实现sqrt的方法。 我的问题是:快速实现pow(x,0.5f)是否比快速实现sqrt(x)更快?
编辑:我的意思是powf-接受浮点数而非双精度数的pow。(双精度数更具误导性)
sqrt
和pow
,答案是否定的。pow(x, .5f)
比sqrt(x)
的实现更快,那么负责维护sqrt的工程师将使用pow(x, .5f)
替换实现。pow
来粗略近似sqrt
。sqrt()
会更快。 - Stephen Canonsqrt
是微不足道的。只需操作浮点表示的位,将指数减半,然后在尾数上进行廉价修复即可... - R.. GitHub STOP HELPING ICE在MSVC++ 2013 64位模式下,完全优化后运行以下代码的结果。sqrt()的性能提高了约9倍。
距离为2619435809228.278300
pow()的耗时为18413.000000毫秒
距离为2619435809228.278300
sqrt()的耗时为2002.000000毫秒
#define LOOP_KNT 249000000 // (SHRT_MAX * 1024)
int main(void) {
time_t start = clock();
double distance = 0, result = 0;
start = clock();
for(int i=0; i<LOOP_KNT; i++) {
result = pow(i, 0.50);
distance += result;
}
printf("\nDistance is %f", distance);
printf("\nPow() elapsed time was %f milliseconds", (double)clock() - (double)(start));
distance = 0, result = 0;
start = clock();
for(int i=0; i<LOOP_KNT; i++) {
result = sqrt(i);
distance += result;
}
printf("\nDistance is %f", distance);
printf("\nSqrt() elapsed time was %f milliseconds", (double)clock() - (double)(start));
printf("\nHit any key to end program.\n");
getchar();
return 0;
}
不需要担心、理论化或者空谈。只需编写基准测试并观察结果。
sqrt
和 pow
都非常慢。 - Zaffypow() vs sqrt()
。 - chux - Reinstate Monica一般来说,在相同的误差限制下,一个更具体的问题可以比一个更普遍的问题更加优化。
因此,您可以采用该算法,并将b替换为常数0.5,现在您拥有的sqrt()至少与pow()一样快。现在它是常数,编译器(或人类)可以基于此进行优化。
请注意,pow()函数是一种近似值,并且具有(相对较大的)误差,因此不像大多数库sqrt函数那样准确。如果您放宽对sqrt的实现的近似限制,确实可以使其至少与pow()一样快。
sqrt()
实现可以被证明精度在 0.5 ULP 以内。pow()
很少有这种可证明的精度。好的实现通常会返回一个精度在 1 ULP 以内的结果。 - chux - Reinstate Monica
0.5
可以在IEEE浮点数中精确表示,因此编译器允许为您重写pow(x, 0.5)
为sqrt(x)
,并且当第二个参数为0.5时,C库允许从pow
内部执行return sqrt(x)
。我不知道是否有任何实现会执行这些操作,但如果有的话,我也不会感到惊讶。 - zwol