JavaScript中最快的阶乘函数是什么?

JavaScript中最快的阶乘函数是什么?,javascript,math,factorial,Javascript,Math,Factorial,正在寻找JavaScript中的阶乘函数的真正快速实现。有什么建议吗?简单的递归函数(也可以通过循环实现,但我认为这不会对性能产生任何影响): 对于一个非常大的n,你可以使用-,但这只会给你一个近似值 编辑:如果能评论一下为什么我会因此而遭到否决,那就太好了 EDIT2:这将是使用循环的解决方案(这将是更好的选择): 函数阶乘(n){ j=1; 对于(i=1;i,您可以预先计算阶乘序列 前100个数字是: 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3

正在寻找JavaScript中的阶乘函数的真正快速实现。有什么建议吗?

简单的递归函数(也可以通过循环实现,但我认为这不会对性能产生任何影响):

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

编辑:如果能评论一下为什么我会因此而遭到否决,那就太好了

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

函数阶乘(n){
j=1;
对于(i=1;i,您可以预先计算阶乘序列

前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
如果仍要自己计算值,可以使用:

编辑:21.08.2014 解决方案2 我认为添加一个惰性迭代阶乘函数的工作示例会很有用,它使用大数字获得精确的结果,并将记忆缓存作为比较

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);
var f=[new BigNumber(“1”)、new BigNumber(“1”)];
var i=2;
函数阶乘(n)
{
if(f[n]的类型!=“未定义”)
返回f[n];
var结果=f[i-1];

对于(;i您应该使用循环

这里有两个版本通过计算100的阶乘10.000次进行基准测试

递归的

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;
}
函数sFact(num)
{
var-rval=1;

对于(var i=2;i我仍然认为Margus的答案是最好的。但是,如果您还想计算0到1范围内的数字的阶乘(即gamma函数),那么您不能使用这种方法,因为查找表必须包含无限值

但是,您可以近似地计算阶乘的值,而且它非常快,至少比递归调用自身或循环它要快(尤其是当值开始变大时)

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

下面是一个JavaScript实现(移植自我几个月前编写的计算器):

函数阶乘(op){
//Gamma函数的Lanczos近似
//如C中的数字配方所述(第二版,剑桥大学出版社,1992年)
var z=op+1;
var p=[1.00000000019015,76.18009172947146,-86.50532032941677,24.0140924083091,-1.231739572450155,1.208650973866179E-3,-5.395239384953E-6];
var d1=数学sqrt(2*Math.PI)/z;
var d2=p[0];

对于(var i=1;i计算阶乘的代码取决于您的需求

  • 你担心溢出吗
  • 您的输入范围是什么
  • 对你来说,最小化尺寸或时间更重要吗
  • 你打算用阶乘做什么
  • 关于第1点和第4点,使用函数直接计算阶乘的日志通常比使用函数计算阶乘本身更有用


    下面是一个讨论这些问题的示例。下面是一些对于移植到JavaScript来说微不足道的示例。但是,根据您对上述问题的回答,它可能不适合您的需要。

    如果您使用的是自然数,那么查找表是一个明显的方法。 要实时计算任何阶乘,您可以使用缓存加速,保存以前计算过的数字。类似于:

    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;
    })();
    

    您可以预先计算一些值以加快计算速度。

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

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

    rFact(x, 1);
    

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

    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对象中,这是一个对象文字,因此没有原型。而只是将其直接绑定到函数。

    我看到了这篇文章。受所有贡献的启发,我提出了自己的版本,它有两个我以前没有见过的功能: 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];
    
    var事实;
    (事实=函数(n){
    if((n=parseInt(n))<0 | | isNaN(n))throw“必须是非负数”;
    var cache=fact.cache,i=cache.length-1;
    而(i
    您可以预先填充缓存,也可以允许在调用过程中填充缓存。但必须存在初始元素(对于事实(0)),否则它将中断


    享受:)

    我相信下面是上述评论中最可持续、最高效的一段代码。您可以在全局应用程序js体系结构中使用它……而且,不用担心在多个名称空间中编写它(因为这是一项可能不需要太多扩充的任务)。我已经包括了两个方法名称(基于偏好)但两者都可以使用,因为它们只是参考

    Math.factorial = Math.fact = function(n) {
        if (isNaN(n)||n<0) return undefined;
        var f = 1; while (n > 1) {
            f *= n--;
        } return f;
    };
    
    Math.factorial=Math.fact=function(n){
    if(isNaN(n)| | n1){
    f*=n--;
    }返回f;
    };
    
    //如果不想更新数学对象,请使用'var factorial=`
    Math.factorial=(函数(){
    var f=函数(n){
    如果(n<1){return 1;}//没有真正的错误检查,则可以添加类型检查
    返回(f[n]>0)?f[n]:f[n]=n*f(n-1);
    }
    对于(i=0;i<101;i++){f(i);}//预先计算一些值
    返回f;
    }());
    阶乘(6);//720,最初缓存
    阶乘[6];//720,同样的东西,访问速度稍微快一点,
    //但在当前缓存限制100以上失败
    阶乘(100);/9.33262154439441e+15
    
    rFact(x, 1);
    
    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
    
    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];
    
    Math.factorial = Math.fact = function(n) {
        if (isNaN(n)||n<0) return undefined;
        var f = 1; while (n > 1) {
            f *= n--;
        } return f;
    };
    
    // 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
    
    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;
    }());
    
    var factorial = function(n) {
      return n > 1
        ? n * factorial(n - 1)
        : n < 0
            ? n * factorial(n + 1)
            : 1;
    }
    
    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;
    }
    
    function fac(n){
        return(n<2)?1:fac(n-1)*n;
    }
    
    f=n=>(n<2)?1:f(n-1)*n
    
    function factorial(num){
        var result = num;
        for(i=num;i>=2;i--){
            result = result * (i-1);
        }
        return result;
    }
    
    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;
      }
    })();
    
    function factorial( _n )
    {
        var _p = 1 ;
        while( _n > 0 ) { _p *= _n-- ; }
        return _p ;
    }
    
    Math.factorial = function( _x )  { return _x <= 1 ? 1 : _x * Math.factorial( --_x ) ; }
    
    Math.factorial = n => n === 0 ? 1 : Array(n).fill(null).map((e,i)=>i+1).reduce((p,c)=>p*c)
    
    function isNumeric(n) {
        return !isNaN(parseFloat(n)) && isFinite(n)
    }
    
    var factorials=[[1,2,6],3];
    
    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;
    });
    
    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);
    });
    
    const factorial = n => !(n > 1) ? 1 : factorial(n - 1) * n;
    
    function computeFactorialOfN(n) {
      var output=1;
      for(i=1; i<=n; i++){
        output*=i;
      } return output;
    }
    computeFactorialOfN(5);
    
    function factorial(number) {
      total = 1
      while (number > 0) {
        total *= number
        number = number - 1
      }
      return total
    }
    
    const factorial = n => [...Array(n + 1).keys()].slice(1).reduce((acc, cur) => acc * cur, 1)
    
    const factorial = n => +!n || n * factorial(--n);
    
    factorial(4) // 4! = 4 * 3 * 2 * 1 = 24
    
    function factorial(n, r = 1) {
      while (n > 0) r *= n--;
      return r;
    }
    
    // Default parameters `r = 1`,
    //   was introduced in ES6
    
    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)