给定r ^ 2,是否有一种有效的方法来计算r ^ 3?

fre*_*low 13 c++ floating-point performance distance square-root

double r2 = dx * dx + dy * dy;
double r3 = r2 * sqrt(r2);
Run Code Online (Sandbox Code Playgroud)

可以用更快的东西替换第二行吗?什么东西不涉及sqrt

Sid*_*Bob 14

怎么样

double r3 = pow(r2,1.5);
Run Code Online (Sandbox Code Playgroud)

如果将sqrt作为pow的特例实现,那将为您节省乘法.在宏伟的计划中心灵不多!

如果您真的在寻求更高的效率,请考虑您是否真的需要r ^ 3.例如,如果您只是测试它(或从它派生的东西)以查看它是否超过某个阈值,那么测试r2而不是例如

const double r3_threshold = 9;

//don't do this
if (r3 > r3_threshold)
    ....

//do do this
const double r2_threshold = pow(r3_threshold,2./3.); 
if (r2 > r2_threshold)
    ....
Run Code Online (Sandbox Code Playgroud)

这种方式pow只会调用一次,甚至可能在编译时调用.

编辑如果你确实需要每次重新计算门限,我认为有关Q_rsqrt的答案值得一看,可能值得超过这个

  • 除非你的数学库真的很糟糕,sqrt()不会通过pow(x,.5)实现,而且它会比pow()快得多(IIRC我在某些时候测试过这个并且在glibc sqrt中使用了libm) ()大约快一个数量级).但是,是的,我想它并没有伤害尝试它.. (6认同)

INS*_*INS 12

使用快速逆sqrt(取Q_rsqrt功能).

你有:

float r2;
// ... r2 gets a value
float invsqrt = Q_rsqrt(r2);
float r3 = r2*r2*invsqrt; // x*x/sqrt(x) = x*sqrt(x)
Run Code Online (Sandbox Code Playgroud)

注意:对于double类型,有一个常量0x5f3759df,可以帮助您编写一个处理double数据类型的函数.

稍后编辑:似乎已经在这里讨论了这种方法.

LATER EDIT2:double维基百科链接中的常量:

Lomont指出,64位IEEE754大小类型double的"幻数"是0x5fe6ec85e7de30da,但实际上它接近0x5fe6eb50c7aa19f9.

  • 自Quake 3撰写以来,时代已经发生了变化.例如,SSE有一个硬件sqrt指令,速度更快. (10认同)
  • @IulianŞerbănoiu:它远不及最快.它比*某些*平台上的平方根指令更快,但大多数主流CPU可以在单个指令中计算更准确的倒数平方根估计,只需要几个周期的延迟(英特尔上的"rsqrtss",PPC上的"frsqrte") ,ARM上的`vrsqrte`). (4认同)
  • 无论你使用Quake技巧还是硬件`1/sqrt`指令,`r ^ 2*r ^ 2/sqrt(r ^ 2)`的思想仍然有效. (4认同)
  • [见这里](http://assemblyrequired.crashworks.org/2009/10/16/timing-square-root/)了解更多信息. (3认同)

Ped*_*ery 1

我认为看待你的问题的另一种方式是“如何计算(或近似)sqrt(n) ”。从那里你的问题将变得微不足道(n * sqrt(n))。当然,您必须定义可以忍受多少错误。维基百科为您提供了多种选择:

http://en.wikipedia.org/wiki/Methods_of_computing_square_roots