JavaScript中最快的因子函数是什么?

时间:2010-10-18 12:40:19

标签: javascript math factorial

在JavaScript中寻找一个非常快速的 factorial 函数实现。有什么建议吗?

47 个答案:

答案 0 :(得分:100)

您可以search for (1...100)! on WolframAlpha预先计算因子序列。

前100个数字是:

1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600, 6227020800, 87178291200, 1307674368000, 20922789888000, 355687428096000, 6402373705728000, 121645100408832000, 2432902008176640000, 51090942171709440000, 1124000727777607680000, 25852016738884976640000, 620448401733239439360000, 15511210043330985984000000, 403291461126605635584000000, 10888869450418352160768000000, 304888344611713860501504000000, 8841761993739701954543616000000, 265252859812191058636308480000000, 8222838654177922817725562880000000, 263130836933693530167218012160000000, 8683317618811886495518194401280000000, 295232799039604140847618609643520000000, 10333147966386144929666651337523200000000, 371993326789901217467999448150835200000000, 13763753091226345046315979581580902400000000, 523022617466601111760007224100074291200000000, 20397882081197443358640281739902897356800000000, 815915283247897734345611269596115894272000000000, 33452526613163807108170062053440751665152000000000, 1405006117752879898543142606244511569936384000000000, 60415263063373835637355132068513997507264512000000000, 2658271574788448768043625811014615890319638528000000000, 119622220865480194561963161495657715064383733760000000000, 5502622159812088949850305428800254892961651752960000000000, 258623241511168180642964355153611979969197632389120000000000, 12413915592536072670862289047373375038521486354677760000000000, 608281864034267560872252163321295376887552831379210240000000000, 30414093201713378043612608166064768844377641568960512000000000000, 1551118753287382280224243016469303211063259720016986112000000000000, 80658175170943878571660636856403766975289505440883277824000000000000, 4274883284060025564298013753389399649690343788366813724672000000000000, 230843697339241380472092742683027581083278564571807941132288000000000000, 12696403353658275925965100847566516959580321051449436762275840000000000000, 710998587804863451854045647463724949736497978881168458687447040000000000000, 40526919504877216755680601905432322134980384796226602145184481280000000000000, 2350561331282878571829474910515074683828862318181142924420699914240000000000000, 138683118545689835737939019720389406345902876772687432540821294940160000000000000, 8320987112741390144276341183223364380754172606361245952449277696409600000000000000, 507580213877224798800856812176625227226004528988036003099405939480985600000000000000, 31469973260387937525653122354950764088012280797258232192163168247821107200000000000000, 1982608315404440064116146708361898137544773690227268628106279599612729753600000000000000, 126886932185884164103433389335161480802865516174545192198801894375214704230400000000000000, 8247650592082470666723170306785496252186258551345437492922123134388955774976000000000000000, 544344939077443064003729240247842752644293064388798874532860126869671081148416000000000000000, 36471110918188685288249859096605464427167635314049524593701628500267962436943872000000000000000, 2480035542436830599600990418569171581047399201355367672371710738018221445712183296000000000000000, 171122452428141311372468338881272839092270544893520369393648040923257279754140647424000000000000000, 11978571669969891796072783721689098736458938142546425857555362864628009582789845319680000000000000000, 850478588567862317521167644239926010288584608120796235886430763388588680378079017697280000000000000000, 61234458376886086861524070385274672740778091784697328983823014963978384987221689274204160000000000000000, 4470115461512684340891257138125051110076800700282905015819080092370422104067183317016903680000000000000000, 330788544151938641225953028221253782145683251820934971170611926835411235700971565459250872320000000000000000, 24809140811395398091946477116594033660926243886570122837795894512655842677572867409443815424000000000000000000, 1885494701666050254987932260861146558230394535379329335672487982961844043495537923117729972224000000000000000000, 145183092028285869634070784086308284983740379224208358846781574688061991349156420080065207861248000000000000000000, 11324281178206297831457521158732046228731749579488251990048962825668835325234200766245086213177344000000000000000000, 894618213078297528685144171539831652069808216779571907213868063227837990693501860533361810841010176000000000000000000, 71569457046263802294811533723186532165584657342365752577109445058227039255480148842668944867280814080000000000000000000, 5797126020747367985879734231578109105412357244731625958745865049716390179693892056256184534249745940480000000000000000000, 475364333701284174842138206989404946643813294067993328617160934076743994734899148613007131808479167119360000000000000000000, 39455239697206586511897471180120610571436503407643446275224357528369751562996629334879591940103770870906880000000000000000000, 3314240134565353266999387579130131288000666286242049487118846032383059131291716864129885722968716753156177920000000000000000000, 281710411438055027694947944226061159480056634330574206405101912752560026159795933451040286452340924018275123200000000000000000000, 24227095383672732381765523203441259715284870552429381750838764496720162249742450276789464634901319465571660595200000000000000000000, 2107757298379527717213600518699389595229783738061356212322972511214654115727593174080683423236414793504734471782400000000000000000000, 185482642257398439114796845645546284380220968949399346684421580986889562184028199319100141244804501828416633516851200000000000000000000, 16507955160908461081216919262453619309839666236496541854913520707833171034378509739399912570787600662729080382999756800000000000000000000, 1485715964481761497309522733620825737885569961284688766942216863704985393094065876545992131370884059645617234469978112000000000000000000000, 135200152767840296255166568759495142147586866476906677791741734597153670771559994765685283954750449427751168336768008192000000000000000000000, 12438414054641307255475324325873553077577991715875414356840239582938137710983519518443046123837041347353107486982656753664000000000000000000000, 1156772507081641574759205162306240436214753229576413535186142281213246807121467315215203289516844845303838996289387078090752000000000000000000000, 108736615665674308027365285256786601004186803580182872307497374434045199869417927630229109214583415458560865651202385340530688000000000000000000000, 10329978488239059262599702099394727095397746340117372869212250571234293987594703124871765375385424468563282236864226607350415360000000000000000000000, 991677934870949689209571401541893801158183648651267795444376054838492222809091499987689476037000748982075094738965754305639874560000000000000000000000, 96192759682482119853328425949563698712343813919172976158104477319333745612481875498805879175589072651261284189679678167647067832320000000000000000000000, 9426890448883247745626185743057242473809693764078951663494238777294707070023223798882976159207729119823605850588608460429412647567360000000000000000000000, 933262154439441526816992388562667004907159682643816214685929638952175999932299156089414639761565182862536979208272237582511852109168640000000000000000000000, 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000

如果您仍想自己计算值,可以使用memoization

var f = [];
function factorial (n) {
  if (n == 0 || n == 1)
    return 1;
  if (f[n] > 0)
    return f[n];
  return f[n] = factorial(n-1) * n;
} ​

编辑:2014年8月21日

解决方案2

我认为添加使用大数字懒惰 迭代 阶乘函数的工作示例会很有用>通过 memoization 缓存作为比较获得完全结果

var f = [new BigNumber("1"), new BigNumber("1")];
var i = 2;
function factorial(n)
{
  if (typeof f[n] != 'undefined')
    return f[n];
  var result = f[i-1];
  for (; i <= n; i++)
      f[i] = result = result.multiply(i.toString());
  return result;
}
var cache = 100;
//due to memoization following line will cache first 100 elements
factorial(cache);

我假设你会使用some kind of closure来限制变量名称的可见性。

参考BigNumber 沙盒JsFiddle

答案 1 :(得分:83)

你应该使用一个循环。

以下两个版本通过计算10.00倍的阶乘100来进行基准测试。

<强>递归

function rFact(num)
{
    if (num === 0)
      { return 1; }
    else
      { return num * rFact( num - 1 ); }
}

迭代

function sFact(num)
{
    var rval=1;
    for (var i = 2; i <= num; i++)
        rval = rval * i;
    return rval;
}

住在:http://jsfiddle.net/xMpTv/

我的结果显示:
- 递归 ~150毫秒
- 迭代 ~5毫秒..

答案 2 :(得分:28)

我仍然认为Margus的答案是最好的。但是,如果您想计算0到1范围内的数字的阶乘(即伽玛函数),那么您就不能使用该方法,因为查找表必须包含无限值。

但是,可以近似阶乘的值,并且它非常快,比递归调用自身或至少循环它更快(特别是当值开始变大时)。

一个很好的近似方法是Lanczos的一个

这是JavaScript中的一个实现(从我几个月前写的计算器中移植过):

function factorial(op) {
 // Lanczos Approximation of the Gamma Function
 // As described in Numerical Recipes in C (2nd ed. Cambridge University Press, 1992)
 var z = op + 1;
 var p = [1.000000000190015, 76.18009172947146, -86.50532032941677, 24.01409824083091, -1.231739572450155, 1.208650973866179E-3, -5.395239384953E-6];

 var d1 = Math.sqrt(2 * Math.PI) / z;
 var d2 = p[0];

 for (var i = 1; i <= 6; ++i)
  d2 += p[i] / (z + i);

 var d3 = Math.pow((z + 5.5), (z + 0.5));
 var d4 = Math.exp(-(z + 5.5));

 d = d1 * d2 * d3 * d4;

 return d;
}

你现在可以做一些很酷的东西,比如factorial(0.41)等等,但是精确度可能有点偏差,毕竟它是结果的近似值。

答案 3 :(得分:16)

查找表是显而易见的方法,如果您正在使用自然数字。 要实时计算任何阶乘,您可以使用缓存加速它,从而节省您之前计算过的数字。类似的东西:

factorial = (function() {
    var cache = {},
        fn = function(n) {
            if (n === 0) {
                return 1;
            } else if (cache[n]) {
                return cache[n];
            }
            return cache[n] = n * fn(n -1);
        };
    return fn;
})();

您可以预先计算某些值,以便进一步加快速度。

答案 4 :(得分:11)

这是我的解决方案:

function fac(n){
    return(n<2)?1:fac(n-1)*n;
}

这是(更少的字符/行)我发现的最简单的方法,只有一个代码行的函数。


编辑:
如果你真的想保存一些字符,可以使用Arrow Function (21字节)

f=n=>(n<2)?1:f(n-1)*n

答案 5 :(得分:8)

简单易用的递归函数(你也可以用循环来做,但我认为这不会对性能产生任何影响):

function factorial (n){
  if (n==0 || n==1){
    return 1;
  }
  return factorial(n-1)*n;
} 

对于非常大的n,您可以使用stirlings approximation - 但这只会给您一个近似值。

编辑:评论为什么我会为此获得一个downvote会很好...

EDIT2:这将是使用循环的解决方案(这将是更好的选择):

function factorial (n){
  j = 1;
  for(i=1;i<=n;i++){
    j = j*i;
  }
  return j;
}

我认为最好的解决方案是使用缓存的值,正如Margus所提到的那样,并使用stirlings approximation来获得更大的值(假设你必须真的很快而且没有 确切地说就是这么大的数字。)

答案 6 :(得分:7)

看哪,记忆者,它采用任何单参数函数并记住它。结果比@ xPheRe的solution略快,包括缓存大小和相关检查的限制,因为我使用短路等等。

function memoize(func, max) {
    max = max || 5000;
    return (function() {
        var cache = {};
        var remaining = max;
        function fn(n) {
            return (cache[n] || (remaining-- >0 ? (cache[n]=func(n)) : func(n)));
        }
        return fn;
    }());
}

function fact(n) {
    return n<2 ? 1: n*fact(n-1);
}

// construct memoized version
var memfact = memoize(fact,170);

// xPheRe's solution
var factorial = (function() {
    var cache = {},
        fn = function(n) {
            if (n === 0) {
                return 1;
            } else if (cache[n]) {
                return cache[n];
            }
            return cache[n] = n * fn(n -1);
        };
    return fn;
}());

我的Chrome机器上的速度比递归版快25倍,比xPheRe快10%。

答案 7 :(得分:6)

只有一行ES6

const factorial =(n) =>!(n > 1) ? 1 : factorial(n - 1) * n;

&#13;
&#13;
const factorial =(n) =>!(n > 1) ? 1 : factorial(n - 1) * n;


function print(value) {
  document.querySelector('.result').innerHTML = value;
}
&#13;
.result {
  margin-left: 10px;
}
&#13;
<input onkeyup="print(factorial(this.value))" type="number"/>

<span class="result">......</span>
&#13;
&#13;
&#13;

答案 8 :(得分:5)

使用ES6非常简单

const factorial = n => n ? (n * factorial(n-1)) : 1;

查看示例here

答案 9 :(得分:5)

我遇到过这篇文章。受到所有贡献的启发,我想出了我自己的版本,它有两个我以前没有见过的功能: 1)检查以确保参数是非负整数 2)使一个单元脱离缓存和功能,使其成为一个自包含的代码位。 为了好玩,我尽量让它变得紧凑。有些人可能会觉得优雅,有些人可能认为它非常模糊。无论如何,这是:

var fact;
(fact = function(n){
    if ((n = parseInt(n)) < 0 || isNaN(n)) throw "Must be non-negative number";
    var cache = fact.cache, i = cache.length - 1;
    while (i < n) cache.push(cache[i++] * i);
    return cache[n];
}).cache = [1];

您可以预先填写缓存,也可以在调用过程中填写缓存。但是初始元素(事实(0)必须存在或者它会破裂。

享受:)

答案 10 :(得分:4)

这是一个解决方案:

function factorial(number) {
  total = 1
  while (number > 0) {
    total *= number
    number = number - 1
  }
  return total
}

答案 11 :(得分:3)

这是一个基于循环的紧凑版本

function factorial( _n )
{
    var _p = 1 ;
    while( _n > 0 ) { _p *= _n-- ; }
    return _p ;
}

或者您可以覆盖Math对象(递归版本):

Math.factorial = function( _x )  { return _x <= 1 ? 1 : _x * Math.factorial( --_x ) ; }

或加入两种方法......

答案 12 :(得分:3)

计算阶乘的代码取决于您的要求。

  1. 你担心溢出吗?
  2. 您将拥有多少输入?
  3. 最小化尺寸或时间对您来说更重要吗?
  4. 你打算如何处理阶乘?
  5. 关于第1点和第4点,使用函数直接评估阶乘的 log 通常更有用,而不是具有评估阶乘本身的函数。

    这是讨论这些问题的blog post。这里有一些C# code for computing log factorial可以轻松移植到JavaScript。但根据您对上述问题的回答,这可能不是最符合您需求的。

答案 13 :(得分:2)

这是一个计算正和负因子的实现。 它快速而简单。

var factorial = function(n) {
  return n > 1
    ? n * factorial(n - 1)
    : n < 0
        ? n * factorial(n + 1)
        : 1;
}

答案 14 :(得分:2)

最快的阶乘函数

我认为这个基于循环的版本可能是最快的阶乘函数。

function factorial(n, r = 1) {
  while (n > 0) r *= n--;
  return r;
}

// Default parameters `r = 1`,
//   was introduced in ES6

这是我的理由:

  • 即使具有备忘录,递归函数也具有函数调用的开销(基本上将函数推入堆栈),其性能比使用循环要差
  • 尽管for循环和while循环具有相似的性能,但是没有初始化表达式和最终表达式的for循环看起来很奇怪;将for(; n > 0;)写为while(n > 0)
  • 可能更好
  • 仅使用两个参数nr,因此从理论上讲,更少的参数意味着更少的时间用于分配内存
  • 使用递减循环来检查n是否为零-我听说过这样的理论:计算机在检查二进制数(0和1)方面比在检查其他整数方面更好。

答案 15 :(得分:2)

根据Wolfram MathWorld

  

阶乘 n positive integer n 定义为

     

n!=n(n-1)...2·1.

因此,您可以使用以下方法获取数字的阶乘:

const factorial = n => +!n || n * factorial(--n);

factorial(4) // 4! = 4 * 3 * 2 * 1 = 24

答案 16 :(得分:2)

使用ES6可以实现快速和短促:

const factorial=n=>[...Array(n+1).keys()].slice(1).reduce((acc,cur)=>acc*cur,1)

答案 17 :(得分:2)

利用canvas { border: 1px solid red; }的事实,我们可以简单地使用完整的查找表,其中只包含171个紧凑的数组元素,占用的内存少于1.4千字节。

运行时复杂度 O(1)最小阵列访问开销的快速查找功能如下所示:

&#13;
&#13;
Number.MAX_VALUE < 171!
&#13;
&#13;
&#13;

这与使用// Lookup table for n! for 0 <= n <= 170: const factorials = [1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800,479001600,6227020800,87178291200,1307674368e3,20922789888e3,355687428096e3,6402373705728e3,121645100408832e3,243290200817664e4,5109094217170944e4,1.1240007277776077e21,2.585201673888498e22,6.204484017332394e23,1.5511210043330986e25,4.0329146112660565e26,1.0888869450418352e28,3.0488834461171387e29,8.841761993739702e30,2.6525285981219107e32,8.222838654177922e33,2.631308369336935e35,8.683317618811886e36,2.9523279903960416e38,1.0333147966386145e40,3.7199332678990125e41,1.3763753091226346e43,5.230226174666011e44,2.0397882081197444e46,8.159152832478977e47,3.345252661316381e49,1.40500611775288e51,6.041526306337383e52,2.658271574788449e54,1.1962222086548019e56,5.502622159812089e57,2.5862324151116818e59,1.2413915592536073e61,6.082818640342675e62,3.0414093201713376e64,1.5511187532873822e66,8.065817517094388e67,4.2748832840600255e69,2.308436973392414e71,1.2696403353658276e73,7.109985878048635e74,4.0526919504877214e76,2.3505613312828785e78,1.3868311854568984e80,8.32098711274139e81,5.075802138772248e83,3.146997326038794e85,1.98260831540444e87,1.2688693218588417e89,8.247650592082472e90,5.443449390774431e92,3.647111091818868e94,2.4800355424368305e96,1.711224524281413e98,1.1978571669969892e100,8.504785885678623e101,6.1234458376886085e103,4.4701154615126844e105,3.307885441519386e107,2.48091408113954e109,1.8854947016660504e111,1.4518309202828587e113,1.1324281178206297e115,8.946182130782976e116,7.156945704626381e118,5.797126020747368e120,4.753643337012842e122,3.945523969720659e124,3.314240134565353e126,2.81710411438055e128,2.4227095383672734e130,2.107757298379528e132,1.8548264225739844e134,1.650795516090846e136,1.4857159644817615e138,1.352001527678403e140,1.2438414054641308e142,1.1567725070816416e144,1.087366156656743e146,1.032997848823906e148,9.916779348709496e149,9.619275968248212e151,9.426890448883248e153,9.332621544394415e155,9.332621544394415e157,9.42594775983836e159,9.614466715035127e161,9.90290071648618e163,1.0299016745145628e166,1.081396758240291e168,1.1462805637347084e170,1.226520203196138e172,1.324641819451829e174,1.4438595832024937e176,1.588245541522743e178,1.7629525510902446e180,1.974506857221074e182,2.2311927486598138e184,2.5435597334721877e186,2.925093693493016e188,3.393108684451898e190,3.969937160808721e192,4.684525849754291e194,5.574585761207606e196,6.689502913449127e198,8.094298525273444e200,9.875044200833601e202,1.214630436702533e205,1.506141741511141e207,1.882677176888926e209,2.372173242880047e211,3.0126600184576594e213,3.856204823625804e215,4.974504222477287e217,6.466855489220474e219,8.47158069087882e221,1.1182486511960043e224,1.4872707060906857e226,1.9929427461615188e228,2.6904727073180504e230,3.659042881952549e232,5.012888748274992e234,6.917786472619489e236,9.615723196941089e238,1.3462012475717526e241,1.898143759076171e243,2.695364137888163e245,3.854370717180073e247,5.5502938327393044e249,8.047926057471992e251,1.1749972043909107e254,1.727245890454639e256,2.5563239178728654e258,3.80892263763057e260,5.713383956445855e262,8.62720977423324e264,1.3113358856834524e267,2.0063439050956823e269,3.0897696138473508e271,4.789142901463394e273,7.471062926282894e275,1.1729568794264145e278,1.853271869493735e280,2.9467022724950384e282,4.7147236359920616e284,7.590705053947219e286,1.2296942187394494e289,2.0044015765453026e291,3.287218585534296e293,5.423910666131589e295,9.003691705778438e297,1.503616514864999e300,2.5260757449731984e302,4.269068009004705e304,7.257415615307999e306]; // Lookup function: function factorial(n) { return factorials[n] || (n > 170 ? Infinity : NaN); } // Test cases: console.log(factorial(NaN)); // NaN console.log(factorial(-Infinity)); // NaN console.log(factorial(-1)); // NaN console.log(factorial(0)); // 1 console.log(factorial(170)); // 7.257415615307999e+306 < Number.MAX_VALUE console.log(factorial(171)); // Infinity > Number.MAX_VALUE console.log(factorial(Infinity)); // Infinity数据类型一样精确且快速。在Javascript中计算查找表 - 正如其他一些答案所暗示的那样 - 会在Number时降低精度。

通过gzip压缩运行时表会将磁盘上的大小从大约3.6减少到1.8千字节。

答案 18 :(得分:2)

为了完整起见,这是一个允许的递归版本 尾调用优化。我不确定是否在JavaScript中执行尾调用优化..

function rFact(n, acc)
{
    if (n == 0 || n == 1) return acc; 
    else return rFact(n-1, acc*n); 
}

要打电话:

rFact(x, 1);

答案 19 :(得分:2)

这是一个迭代解决方案,它使用更少的堆栈空间并以自我记忆的方式保存以前计算的值:

Math.factorial = function(n){
    if(this.factorials[n]){ // memoized
        return this.factorials[n];
    }
    var total=1;
    for(var i=n; i>0; i--){
        total*=i;
    }
    this.factorials[n] = total; // save
    return total;
};
Math.factorials={}; // store

另请注意,我将此添加到Math对象,这是一个对象文字,因此没有原型。而只是直接将这些绑定到函数。

答案 20 :(得分:2)

function isNumeric(n) {
    return !isNaN(parseFloat(n)) && isFinite(n)
}
  

http://javascript.info/tutorial/number-math提供,作为评估对象是否是用于计算的正确整数的简单方法。

var factorials=[[1,2,6],3];
  

需要冗余计算的一组简单的Memoized阶乘,可以用&#34;乘以1&#34;来处理,或者是一个不值得处理的简单等式的数字。

var factorial = (function(memo,n) {
    this.memomize = (function(n) {
        var ni=n-1;
        if(factorials[1]<n) {
            factorials[0][ni]=0;
            for(var factorial_index=factorials[1]-1;factorials[1]<n;factorial_index++) {
                factorials[0][factorials[1]]=factorials[0][factorial_index]*(factorials[1]+1);
                factorials[1]++;
            }
        }
    });
    this.factorialize = (function(n) {
        return (n<3)?n:(factorialize(n-1)*n);
    });
    if(isNumeric(n)) {
        if(memo===true) {
            this.memomize(n);
            return factorials[0][n-1];
        }
        return this.factorialize(n);
    }
    return factorials;
});

在审查了其他成员的输入(不包括Log建议,虽然我可能稍后实现)之后,我继续将一个非常简单的脚本组合在一起。我从一个简单的未受过教育的JavaScript OOP示例开始,并构建了一个小类来处理阶乘。然后,我实现了上面建议的我的Memoization版本。我还实现了速记因子化,但我做了一个小错误调整;我改变了&#34; n&lt; 2&#34;至&#34; n&lt; 3&#34; &#34; N&2&#34;仍会处理n = 2,这将是一种浪费,因为你会迭代2 * 1 = 2;在我看来,这是浪费。我把它改成了&#34; n&lt; 3&#34 ;;因为如果n是1或2,它将简单地返回n,如果它是3或更多,它将正常评估。当然,当规则适用时,我将我的函数按假设执行的降序排列。我添加了bool(true | false)选项,允许在备忘录和正常执行之间快速更改(您永远不知道何时需要在页面上进行交换而无需更改&#34;样式&#34 ;) 正如我之前所说,memoized factorials变量设置为3个起始位置,取4个字符,并最大限度地减少浪费的计算。通过第三次迭代的所有内容都是处理双位数学加。我想如果你在一个关于它的地方,你会在一个阶乘表上运行(如实现的那样)。

此后我有什么计划? 本地和会话存储,以允许逐个缓存所需的迭代,基本上处理&#34;表&#34;上面提到的问题。这也将大量节省数据库和服务器端空间。但是,如果你使用localStorage,你实际上只是在用户计算机上占用空间只是为了存储一个数字列表并使他们的屏幕更快,但是在很长一段时间内需要很大的时间这将是很慢的。我认为sessionStorage(Tab离开后清除)将是一个更好的路线。可能将它与自平衡服务器/本地相关缓存结合起来? 用户A需要X次迭代。 用户B需要Y次迭代。 X + Y / 2 =本地缓存所需的金额。 然后只需为每个用户检测并调整加载时间和执行时基准,直到它调整自身以优化站点本身。 谢谢!

编辑3:

var f=[1,2,6];
var fc=3;
var factorial = (function(memo) {
    this.memomize = (function(n) {
        var ni=n-1;
        if(fc<n) {
            for(var fi=fc-1;fc<n;fi++) {
                f[fc]=f[fi]*(fc+1);
                fc++;
            }
        }
        return f[ni];
    });

    this.factorialize = (function(n) {
        return (n<3)?n:(factorialize(n-1)*n);
    });

    this.fractal = (function (functio) {
        return function(n) {
            if(isNumeric(n)) {
                return functio(n);
            }
            return NaN;
        }
    });

    if(memo===true) {
        return this.fractal(memomize);
    }
    return this.fractal(factorialize);
});
  

此编辑实现了另一个Stack建议,并允许我将该函数称为factorial(true)(5),这是我设定的目标之一。 :3我还删除了一些不必要的赋值,并且缩短了一些非公共变量名称。

答案 21 :(得分:2)

// if you don't want to update the Math object, use `var factorial = ...`
Math.factorial = (function() {
    var f = function(n) {
        if (n < 1) {return 1;}  // no real error checking, could add type-check
        return (f[n] > 0) ? f[n] : f[n] = n * f(n -1);
    }
    for (i = 0; i < 101; i++) {f(i);} // precalculate some values
    return f;
}());

factorial(6); // 720, initially cached
factorial[6]; // 720, same thing, slightly faster access, 
              // but fails above current cache limit of 100
factorial(100); // 9.33262154439441e+157, called, but pulled from cache
factorial(142); // 2.6953641378881614e+245, called
factorial[141]; // 1.89814375907617e+243, now cached

这会动态缓存前100个值,并且不会将外部变量引入缓存的范围,将值存储为函数对象本身的属性,这意味着如果您知道{{1}已经计算过了,您可以简单地将其称为factorial(n),效率稍高一些。在现代浏览器中运行这些前100个值将花费亚毫秒时间。

答案 22 :(得分:2)

这是我的代码

function factorial(num){
    var result = num;
    for(i=num;i>=2;i--){
        result = result * (i-1);
    }
    return result;
}

答案 23 :(得分:1)

一开始可能非常简单,也许从这个简短的代码中你可以根据自己的需要更好地设置它:

>>> a = [i for i in range(4)]
>>> list(a)
[0, 1, 2, 3]
>>> list(a)
[0, 1, 2, 3]

答案 24 :(得分:1)

这是我自己制作的,不要使用超过170或低于2的数字。

function factorial(x){
 if((!(isNaN(Number(x)))) && (Number(x)<=170) && (Number(x)>=2)){
  x=Number(x);for(i=x-(1);i>=1;--i){
   x*=i;
  }
 }return x;
}

答案 25 :(得分:1)

这将返回n

的阶乘
function f(n) {
    var e = n;
    if (e == 1 | e == 0) return 1;
    while (n--) {
        if (n < 1)
            break;
        e *= n;
    }
    return e
}

答案 26 :(得分:1)

function computeFactorialOfN(n) {
  var output=1;
  for(i=1; i<=n; i++){
    output*=i;
  } return output;
}
computeFactorialOfN(5);

答案 27 :(得分:1)

您可以使用

git difftool stash@{n} -- path/to/file

答案 28 :(得分:1)

这是我所知道的最简单的方法来制作阶乘函数

function factorial(num) {

    var result = 1;
    for(var i = 2; i<= num; i++) {
        result *= i;
    }
    return result;
}

答案 29 :(得分:1)

使用ES6功能,可以在 ONE line &amp; 没有递归

var factorial=(n)=>Array.from({length:n},(v,k)=>k+1).reduce((a,b)=>a*b,1)

答案 30 :(得分:1)

    function factorial(num){    
        var num=Number(num);
        if (num < 0){
            return "this is not a positive number";
        }
        else{

        for (i=2 , f=1 ; i<=num;i++){

        f=f*i;

        }

    return f;
    }
    }
    // the function assumes that a number < 0 is null and factorial of any word is considerate as factorial of 0 //

    console.log("-5! ="+factorial(-1));
    console.log("something ="+factorial("something"));
    console.log("15! ="+factorial(15));
    console.log("20! ="+factorial(20));

答案 31 :(得分:1)

以下是使用较新的javascript函数fillmapreduceconstructor(以及胖箭头语法)的内容:

Math.factorial = n => n === 0 ? 1 : Array(n).fill(null).map((e,i)=>i+1).reduce((p,c)=>p*c)

编辑:更新以处理n === 0

答案 32 :(得分:1)

缓存循环应该是最快的(至少在多次调用时)

var factorial = (function() {
  var x =[];

  return function (num) {
    if (x[num] >0) return x[num];
    var rval=1;
    for (var i = 2; i <= num; i++) {
        rval = rval * i;
        x[i] = rval;
    }
    return rval;
  }
})();

答案 33 :(得分:0)

一行答案:

const factorial = (num, accumulator) => num <= 1 ? accumulator || 1 : factorial(--num, num * (accumulator || num + 1));

factorial(5); // 120
factorial(10); // 3628800
factorial(3); // 6
factorial(7); // 5040
// et cetera

答案 34 :(得分:0)

这是尚未提供的一种方法。使用BigInt和备忘录,我们可以获得准确的结果,并跳过对已经计算出的值的计算:

// using let and const, block scope can be used instead of IIFE for closure
{
  const lut = [1n, 1n];
  
  // returns factorial as BigInt instead of Number
  function factorial (n) {
    for (let i = lut.length; i <= n; i++) {
      lut.push(BigInt(i) * lut[i - 1]);
    }

    return lut[n];
  }
}

console.log('starting');
// first time will require computation
console.log(factorial(10000).toString());
// second time will return result from cache
console.log(factorial(10000).toString());
div.as-console-wrapper { overflow-x: scroll; }

答案 35 :(得分:0)

她是我使用IIFy函数和递归的解决方案:

console.log((function factorial(n){return (n>1)?n*factorial(n-1):1;})(10))

这是在单行代码中获得阶乘输出的最佳解决方案。

答案 36 :(得分:0)

为安全起见,使用BigInt进行迭代阶乘

  

解决方案使用BigInt(一种ES 2018 + / 2019功能)。

这个有效的示例使用BigInt,因为这里的许多答案都几乎立即逃脱了Number(MDN)的安全边界。它不是最快的,但是它很简单,因此更容易适应其他优化(例如前100个数字的缓存)。

function factorial(nat) {
   let p = BigInt(1)
   let i = BigInt(nat)

   while (1 < i--) p *= i

   return p
}

用法示例

// 9.332621544394415e+157
Number(factorial(100))

// "933262154439441526816992388562667004907159682643816214685929638952175999
//  932299156089414639761565182862536979208272237582511852109168640000000000
//  00000000000000"
String(factorial(100))

// 9332621544394415268169923885626670049071596826438162146859296389521759999
// 3229915608941463976156518286253697920827223758251185210916864000000000000
// 000000000000n
factorial(100)
  • n这样的数字文字末尾的1303n表示它是BigInt类型。
  • 请记住,除非您明确地将BigIntNumber混合使用,否则可能会导致准确性下降。

答案 37 :(得分:0)

针对迭代和递归选项的单行解决方案;

const rf = n => 1 === n ? 1 : rf( n - 1 ) * n;

const sf = n => {for (var i = n, c = 1; i > 1; i --) c *= i; return c;}

答案 38 :(得分:0)

虽然以上所有都很好,但对我来说它们似乎都太长了,所以我自己做了。

function factorial(n) {              //"n" is the number used in the factorial

    var ans = 1,                     //define the base variables
        neg = false,
        n = Math.round(n);

    if (n<0 || !n) neg = true;       //check if the number is negative or if the number doesn't exist

    for (var i=1;i<=n;i++) ans *= i; //the actual repeating code, won't run if the number is less than or equal to 0

    return neg ? NaN : ans;          //return the answer if the original was positive

}

for循环的工作方式将自动不对任何低于1的数字做任何事情。所以基本上&#34;如果(数字)小于或等于0,则返回{ {1}}。

1if (n<0 || !n) neg = true;共同说明&#34;如果数字为负数,则返回return neg ? NaN : ans;(非数字)&#34;。这些也检查数字是否存在,如果数字不存在,将返回NaN(非数字)。

注意

至少在Chrome v50.0.2661.86(64位)上,它的最大值为170.因此,如果您在高于170(例如171)的数字上运行此函数,它将返回{{1} }。

答案 39 :(得分:0)

var factorial = (function() {
    var cache = [1];
    return function(value) {
        for (var index = cache.length; index <= value; index++) {
            cache[index] = index * cache[index - 1]
        }
        return cache[value];
    }
})();

我觉得这在同样的情况下很有用:

function factorialDivision(n, d) {
    var value = 1;
    for (d++ < n) {
        value *= d;
    }
    return value;
}

答案 40 :(得分:0)

迭代: mysql -u root -p

递归: Math.factorial=n=>{for(var o=n;n>1;)o*=--n;return o};

预先计算的: Math.factorial=n=>n>1?n--*Math.fac(n):1;

https://code.sololearn.com/Wj4rlA27C9fD。在这里,我可能会发布更多解决方案。

答案 41 :(得分:0)

var factorial = function(numToBeFactored)
    {
        if (numToBeFactored == 0)
                return 1;
            var numLength = 0;
            var numBeingFactored = 1;
        /*goes through the loop numToBeFactored times and each time multiplies numBeingFactored by one less than the last loop*/
            for (numLength = 0; numLength < numToBeFactored; numLength++)
            {
                numBeingFactored *= (numToBeFactored - numLength);
            }
            return numBeingFactored;
    };

答案 42 :(得分:0)

 used closure  for this with the helper (getFact) , I think this approach is neat hope this helps  


    factorial of n : using closures*/

    function getFact(num) {

        if (num > 1)
            return num * getFact(num - 1);
        else
            return 1;

    }


    function makeFact(fn) {
        return function(num) {
            return fn(num);
        }


    }

   makeFact(getFact)(5) //120

答案 43 :(得分:0)

因为阶乘只是从给定的数字到1的退化乘法,所以在循式乘法中确实更容易:

Math.factorial = function(n) {

  if (n === 0||n === 1) {

    return 1;

  } else {

    for(var i = n; i > 0; --i) { //always make sure to decrement the value BEFORE it's tacked onto the original as a product
      n *= i;
    }

    return n;

  }

}

答案 44 :(得分:-1)

这个问题有足够多的答案,但只是为阶乘和反向因子发布一个可读,快速和简短的解决方案。

{
    const cache = [1, 1];
    let i = 2;

    function factorial(n) {
        if (!isFinite(n = parseInt(n)) || n < 0)
            throw new Error('argument for factorial has to be a positive finite integer but was ' + n);

        for (; i <= n; i++)
            cache[i] = cache[i - 1] * i;

        return cache[n];
    }

    function reverseFactorial(n) {
        if (!isFinite(n = parseFloat(n)) || n < 0)
            throw new Error('argument for reverseFactorial has to be a positive finite floatingpoint number but was ' + n);

        let f = 1;

        while (true)
            if (factorial(++f) >= n)
                return f - 1; // lower bound (f! which will fit in the given n, for upper bound just return f)

    }
}

reverseFactorial将返回k,这是最适合给定n的k!

这两个函数都由factorial构建缓存的利润。

如果你想稍微测试一下:

for (let i = 0; i < 10; i++) {
    let random = Math.random() * 100;
    random = factorial(random) * Math.random() * random;

    const reverse = reverseFactorial(random);
    const resultOfReverse = factorial(reverse);

    function expo(x) {
        return x.toExponential(2);
    }

    console.log('%s fits %d! which is %s (upper bound %d! is %s)', expo(random), reverse, expo(resultOfReverse), reverse + 1, expo(factorial(reverse + 1)));
}

答案 45 :(得分:-1)

老问题,但我发现这种方法非常简单易懂

function factorialize(num) {
  var arr = [];
  var result;
  if ( num === 0 || num === 1 ) {
    return 1;
  } else {
    for (var i = num; i > 0; i--) {
      arr.push(i);
      result = arr.reduce(function(previousVal, nextVal){
                return previousVal * nextVal;
              });
    }
    return result;
  }
}

答案 46 :(得分:-2)

    var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    numbers.reduce(function factorial(previous, current) {
      return previous * current;
      });

   console.log(numbers);