Math.sqrt()的更快替代方案

时间:2017-01-01 09:10:49

标签: javascript performance math math.sqrt

有没有其他方法可以使用Math.sqrt()来获取未知值的平方根?

例如:

var random  = (Math.random() * (999 - 1)) + 1;
var sqrt = Math.sqrt(random);

我听说使用Math.sqrt()获取数字的平方根是一个非常慢的操作,我只是想知道是否有更快的方法可以获得随机数的平方根。对此的任何帮助将不胜感激。

6 个答案:

答案 0 :(得分:6)

如果不是更好的话,你可以确定你编写自己的最快算法已经在Math.sqrt中实现了。

有一种算法可以通过数字直到中间(有些只是计算):Writing your own square root function

但正如我所说,如果不是更好的话,可能会实施。

您可以尝试查找某些特定的业务/域逻辑,以减少数字范围。

答案 1 :(得分:2)

如果您拥有的代码与您使用的代码相同,则根本不需要平方根

var random  = (Math.random() * (999 - 1)) + 1;
var sqrt = Math.sqrt(random);

可能是

var sqrt  = (Math.random() * ( 31.6069612586)) + 1;
var random  = sqrt * sqrt ;

乘法比sqrt快得多,所以代码应该类似

注意998的平方根可以像上面那样预先计算,以使其成为一次操作而不是每次运行

答案 2 :(得分:1)

您与sqrt的分配不一致,正如您在计数中所看到的那样。要获得相同的分布,您需要一个更改分布的因子。该因子取决于随机数。没有捷径。

function getRandom() {
    return Math.sqrt((Math.random() * (999 - 1)) + 1);
}

var i, r,
    o = {};

for (i = 0; i < 32; i++) {
    o[i] = 0;
}

for (i = 0; i < 100000; i++) {
    o[Math.floor(getRandom())]++;
}

console.log(o);
.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 3 :(得分:1)

不知道你的sqrt是如何实现的(不是javascript编码器)所以我只能推测什么更快,但很少有快速方法使用&#34;魔术数字&#34;适用于 IEEE 754 float/double 格式,也适用于integers,例如Quake3。只有少数操作在定义的时间间隔内,这或多或少精确,并且很可能比你的sqrt快,但只能在特定的时间间隔内使用。

通常的sqrt实施是通过以下方式完成的:

  1. 近似多项式

    通常使用泰勒级数,切比雪夫等扩展,并且热量的数量取决于目标精度。并非所有数学函数都可以像这样计算。

  2. 迭代逼近

    牛顿,Babylonian等方法很少,通常会收敛得足够快,所以不需要使用太多的热量。我的赌注是你sqrt使用牛顿近似值。

    还有基于二进制搜索的计算

    二进制搜索需要相同的迭代次数,然后使用数字结果位,这通常比上面提到的近似方法更常用。但是对sqrt的二元搜索有一个巨大的优势,那就是它可以在没有乘法的情况下完成(这对于bignums很重要......)

    还有其他搜索近似值,如:

  3. 以代数方式使用log2,exp2

    您可以直接从powlog2,exp2计算sqrt(x)=pow(x,0.5),所以请参阅

  4. <强> LUT

    您可以对预先计算的查找表使用分段插值。

  5. 混合方法

    您可以将更多方法组合在一起,例如使用低精度近似多项式进行估计结果,然后使用二进制搜索搜索它(只需几位)......但这仅对&#34;大&#34;数字(以比特的方式)......

  6. 可以使用PCA

    计算一些数学运算和常量

    但我觉得在你的情况下使用它没有意义......

  7. 有关更多信息,请查看相关的质量检查

    当你根本不计算它时,不知道你在计算什么,但最快sqrt。可以重写许多计算和算法,因此它们根本不需要使用sqrt或至少不需要经常使用(例如比较距离^ 2等...)。

    如果您想这样做,请参阅:

    x = Random();
    y = sqrt(x);
    

    您可以将其重写为:

    y= Random();
    x = y*y;
    

    但要注意随机性属性不一样!!!

答案 4 :(得分:0)

我认为你可以获得比内置的预编译代码更快的速度,但是对于你的信息,你可以找到关于如何用纯JS获得数字的平方根的算法。

它非常快,但由于它的递归,它很可能比它的迭代版本慢一些。迭代实现取决于您。

&#13;
&#13;
var sqrt = (n, u = n, d = n-1 ? n/u : 1) => n ? (u === (u+d)/2) && (d === n/u) ? d : sqrt(n,(u+d)/2, n/u) : 0,
       s = 0;
console.time("sqrt");
var s = sqrt(9876543210*9876543210);
console.timeEnd("sqrt");
console.log(s);

console.time("sqrt");
var s = sqrt(98765.4321*98765.4321);
console.timeEnd("sqrt");
console.log(s);
&#13;
&#13;
&#13;

它使用Babylonian method

答案 5 :(得分:0)

数学规定:

var sqrt = Math.sqrt(random);

等效于:

var sqrt = random**.5;

可能不会更快,但绝对会更短。