Если вы все еще хотите вычислить значения самостоятельно, вы можете использовать мемоизацию :
var f = [];
functionfactorial (n) {
if (n == 0 || n == 1)
return1;
if (f[n] > 0)
return f[n];
return f[n] = factorial(n-1) * n;
}
Изменить: 21.08.2014
Решение 2
Я подумал, что было бы полезно добавить рабочий пример ленивой итеративной факториальной функции, которая использует большие числа для получения точного результата с мемоизацией и кешем для сравнения.
var f = [new BigNumber("1"), new BigNumber("1")];
var i = 2;
functionfactorial(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);
Я предполагаю, что вы использовали бы какое-то закрытие, чтобы ограничить видимость имени переменной.
Значения после 6402373705728000 будут усечены, поэтому, если вы собираетесь использовать этот подход, убедитесь, что преобразовали в экспоненциальный, прежде чем использовать вышеупомянутую таблицу.
Дэвид Скотт Кирби
1
@DavidScottKirby Javascript автоматически преобразует эти числа в их ближайшее 64-битное представление с плавающей запятой. Настоящее преимущество отсутствия в коде чисел полной точности - уменьшение размера файла.
le_m 09
Ваше второе решение можно упростить, чтобы function factorial (n) { for (var i = f.length; i <= n; i++) f.push(f[i - 1].multiply(i.toString())); return f[n]; }увидеть также мой ответ, в котором используется более поздняя встроенная, BigIntа не сторонняя библиотека.
Патрик Робертс,
Итак, 100-е число состоит из 158 символов
Barbu Barbu
99
Вам следует использовать петлю.
Вот две версии, протестированные путем вычисления факториала 100 в 10.000 раз.
Рекурсивный
functionrFact(num)
{
if (num === 0)
{ return1; }
else
{ return num * rFact( num - 1 ); }
}
Итеративный
functionsFact(num)
{
var rval=1;
for (var i = 2; i <= num; i++)
rval = rval * i;
return rval;
}
+1 Отличный ответ! Хотя мемоизация может быть разумной, когда есть несколько вызовов для вычисления факториалов для больших чисел.
Tadeck
@Tadeck, спасибо. Действительно, мемоизация очень полезна в этом случае, и поэтому ответ Маргуса выбран как правильный :)
Габриэле Petrioli
Однострочная версия рекурсии: function factorial (num) {return (num == 1)? число: число * аргументы. callee (число-1); }
jbyrd 03
2
@HWTech, вы никогда не вызываете методы. Ваш тест сравнивает скорость определения двух методов ... а не время, необходимое для их выполнения ... Это лучше тест (с использованием только факториала 15)
Габриэле Петриоли
4
Вместо rval = rval * i;вас можно было написатьrval *= i;
Райан
29
Я по-прежнему считаю, что ответ Маргуса лучший. Однако, если вы хотите вычислить факториалы чисел в диапазоне от 0 до 1 (т.е. гамма-функцию), вы не можете использовать этот подход, потому что таблица поиска должна содержать бесконечные значения.
Однако вы можете аппроксимировать значения факториалов, и это довольно быстро, быстрее, чем рекурсивный вызов самого себя или, по крайней мере, цикл (особенно, когда значения начинают увеличиваться).
Хороший метод приближения - метод Ланцоша.
Вот реализация на JavaScript (перенесенная с калькулятора, который я написал несколько месяцев назад):
functionfactorial(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)и т. Д., Но точность может быть немного неточной, в конце концов, это приблизительное значение результата.
Просто сэкономил мне массу времени, большое спасибо :)
nicolaskruchten
Я рекомендую изменить часть под циклом for на var d3d4 = Math.exp((z + 0.5) * Math.log(z + 5.5) - z - 5.5); return d1 * d2 * d3d4;. Это позволяет вам вычислять факториалы до 169! вместо нынешних всего 140 !. Это довольно близко к максимально представимому факториалу с использованием Numberтипа данных, который равен 170 !.
le_m 09
18
Таблица поиска - очевидный путь, если вы работаете с натуральными числами. Чтобы вычислить любой факториал в реальном времени, вы можете ускорить его с помощью кеша, сохранив числа, которые вы вычисляли ранее. Что-то типа:
На основе этого ответа я создал автоматическую запоминание для любой заданной функции (также немного быстрее :)), включая ограничение на размер кеша. stackoverflow.com/a/10031674/36537
Phil H
16
Вот мое решение:
functionfac(n){
return(n<2)?1:fac(n-1)*n;
}
Это самый простой способ (меньше символов / строк), который я нашел, только функция с одной строкой кода.
Изменить:
если вы действительно хотите сохранить несколько символов, вы можете использовать стрелки (21 байт) :
Я думаю , что лучшим решением было бы использовать кэшированные значения, как уже упоминалось Маргус и использовать приближение stirlings для больших значений (предполагается , что вы должны быть действительно быстро и не должны быть , что точно на таких больших чисел).
В языках без оптимизации хвостового вызова (то есть в наиболее широко используемых языках) лучше использовать нерекурсивную реализацию, где это легко сделать, хотя есть способы обойти это: paulbarry.com/articles/2009/08/30 / tail-call-
optimisation
это действительно определенно не так быстро, поскольку в нем даже не использовалась бы совокупная стоимость владения, если бы она была реализована. Но это просто, и я бы не стал его отрицать. Это точно не самый быстрый.
haylem
Оптимизация хвостового вызова даже невозможна для этой функции, так как рекурсивный вызов не находится в хвостовой позиции.
Фред Фу,
3
@Josh, ( не тот, кто проголосовал против ), самый быстрый цикл с
большим
7
Взгляните на мемоизатор, который принимает любую функцию с одним аргументом и запоминает ее. Оказывается, он немного быстрее, чем решение @ xPheRe , включая ограничение на размер кеша и связанную проверку, потому что я использую сокращение и так далее.
Я думаю, что эта версия на основе цикла может быть самой быстрой факториальной функцией.
functionfactorial(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)
Используются только два параметра nи r, поэтому теоретически меньше параметров означает меньше времени, затрачиваемого на выделение памяти.
Использует декрементированный цикл, который проверяет, nравно ли нулю - я слышал теории о том, что компьютеры лучше проверяют двоичные числа (0 и 1), чем другие целые числа.
Я наткнулся на этот пост. Вдохновленный всеми представленными здесь материалами, я придумал свою собственную версию, в которой есть две функции, которые я раньше не видел: 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) должен присутствовать, иначе он сломается.
Код для вычисления факториала зависит от ваших требований.
Вас беспокоит переполнение?
Какой диапазон входов у вас будет?
Для вас важнее минимизировать размер или время?
Что вы собираетесь делать с факториалом?
Что касается пунктов 1 и 4, часто бывает более полезно иметь функцию для оценки журнала факториала напрямую, чем иметь функцию для оценки самого факториала.
Вот сообщение в блоге, в котором обсуждаются эти проблемы. Вот некоторый код C # для вычисления лог-факториала, который было бы тривиально перенести на JavaScript. Но это может не подходить для ваших нужд в зависимости от ваших ответов на вопросы выше.
Воспользовавшись тем фактом, что Number.MAX_VALUE < 171!мы можем просто использовать полную таблицу поиска, состоящую всего из 171 элемента компактного массива, занимающего менее 1,4 килобайт памяти.
Тогда функция быстрого поиска со сложностью выполнения O (1) и минимальными накладными расходами на доступ к массиву будет выглядеть следующим образом:
Это так же точно и быстро, как и при использовании Numberтипа данных. Вычисление таблицы поиска в Javascript - как предлагают некоторые другие ответы - снизит точность, когда n! > Number.MAX_SAFE_INTEGER.
Сжатие таблицы времени выполнения с помощью gzip уменьшает ее размер на диске примерно с 3,6 до 1,8 килобайт.
Решение использует BigIntфункцию ES 2018 + / 2019.
Это рабочий пример использования BigInt, потому что многие ответы здесь почти сразу выходят за безопасную границу Number(MDN). Это не самый быстрый, но простой и, следовательно, более понятный способ адаптации других оптимизаций (например, кеш первых 100 чисел).
functionfactorial(nat) {
let p = BigInt(1)
let i = BigInt(nat)
while (1 < i--) p *= i
return p
}
var factorial=(n)=>Array.from(
{length: n}, (v, k) => k+1) /*Generate Array [1, 2, .., n -1, n]*/
.reduce(
(a, b) => a*b, 1/*Multiply all aarray items; one with the next*/
);
var n = prompt('Give us "n", we will calculate "n!" ?');
if (n) {
alert(`${n}! = ${factorial(n)}`)
}
Просто для полноты, вот рекурсивная версия, которая позволяет оптимизировать хвостовой вызов. Я не уверен, что оптимизация хвостовых вызовов выполняется в JavaScript ...
functionrFact(n, acc)
{
if (n == 0 || n == 1) return acc;
elsereturn rFact(n-1, acc*n);
}
Также обратите внимание, что я добавляю это к объекту Math, который является литералом объекта, поэтому прототипа нет. Скорее просто привязывайте их к функции напрямую.
На самом деле это не в полной мере использует преимущества мемоизации для подзадач - например, Math.factorial(100); Math.factorial(500);дважды вычисляет умножение 1..100.
Barett
2
Я считаю, что следующий фрагмент кода является наиболее устойчивым и эффективным из приведенных выше комментариев. Вы можете использовать это в своей глобальной архитектуре js приложения ... и не беспокойтесь о том, чтобы писать его в нескольких пространствах имен (поскольку это задача, которая, вероятно, не требует значительного дополнения). Я включил два имени метода (в зависимости от предпочтений), но оба могут использоваться, поскольку они просто ссылки.
Math.factorial = Math.fact = function(n) {
if (isNaN(n)||n<0) returnundefined;
var f = 1; while (n > 1) {
f *= n--;
} return f;
};
Начав умножение с n * (n-1) * (n-2) * ... * 1вместо наоборот, вы потеряете до 4 цифр в точности для n >> 20.
le_m 09
2
// if you don't want to update the Math object, use `var factorial = ...`Math.factorial = (function() {
var f = function(n) {
if (n < 1) {return1;} // no real error checking, could add type-checkreturn (f[n] > 0) ? f[n] : f[n] = n * f(n -1);
}
for (i = 0; i < 101; i++) {f(i);} // precalculate some valuesreturn 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 значений на лету и не вводит внешнюю переменную в область действия кеша, сохраняя значения как свойства самого объекта функции, что означает, что, если вы знаете, factorial(n)что уже вычислено, вы можете просто назовите его factorial[n], что немного эффективнее. Запуск этих первых 100 значений в современных браузерах займет менее миллисекунды.
Начав умножение с n * (n-1) * (n-2) * ... * 1, а не наоборот, вы потеряете до 4 цифр в точности для n >> 20. Кроме того, создается нежелательный глобальная переменная iи выполняет слишком много Numberпреобразований и дает неверные результаты для 0! (как вы сказали, но почему?).
le_m 09
2
Вот мой код
functionfactorial(num){
var result = num;
for(i=num;i>=2;i--){
result = result * (i-1);
}
return result;
}
Если (n> 170) e = Бесконечность. И ваш код сгенерирует огромное количество. не будет ли переполнений?
Prime
Неверный результат для factorial(0). Кроме того, начав умножение с n * (n-1) * (n-2) * ... * 1, а не наоборот, вы потеряете до 4 цифр в точности для n >> 20. @prime: 170! > Number.MAX_VALUEи лучше всего представлен с помощью Infinity.
le_m 09
2
Кешированный цикл должен быть самым быстрым (по крайней мере, при многократном вызове)
var factorial = (function() {
var x =[];
returnfunction (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;
}
})();
Простой набор мемоизированных факториалов, которые требуют избыточных вычислений, могут быть обработаны с помощью "умножения на 1" или представляют собой одну цифру, которая представляет собой простое уравнение, не стоящее обработки вживую.
Изучив ввод от других участников (за исключением рекомендаций журнала, хотя я могу реализовать это позже), я пошел дальше и составил довольно простой сценарий. Я начал с простого необразованного примера ООП на JavaScript и построил небольшой класс для обработки факториалов. Затем я реализовал свою версию мемоизации, предложенную выше. Я также реализовал сокращенную факториализацию, но сделал небольшую корректировку ошибок; Я изменил «n <2» на «n <3». «n <2» по-прежнему будет обрабатывать n = 2, что было бы пустой тратой, потому что вы бы выполняли итерацию для 2 * 1 = 2; на мой взгляд, это бесполезная трата. Я изменил его на «n <3»; потому что, если n равно 1 или 2, он просто вернет n, если он равен 3 или более, он будет оцениваться нормально. Конечно, поскольку применяются правила, я разместил свои функции в порядке убывания предполагаемого выполнения. Я добавил опцию bool (true | false), чтобы разрешить быстрое переключение между memo'ed и нормальным выполнением (вы просто никогда не знаете, когда вы захотите поменять местами на своей странице, не изменяя «стиль»). Как я уже говорил перед Переменная memoized factorials задается с 3 начальными позициями, принимает 4 символа и сводит к минимуму бесполезные вычисления. После третьей итерации вы обрабатываете двузначный математический плюс. Я полагаю, если вы достаточно привержены этому, вы бы использовали факториальную таблицу (как реализовано). взяв 4 символа и минимизируя бесполезные вычисления. После третьей итерации вы обрабатываете двузначный математический плюс. Я полагаю, если вы достаточно привержены этому, вы бы использовали факториальную таблицу (как реализовано). взяв 4 символа и минимизируя бесполезные вычисления. После третьей итерации вы обрабатываете двузначный математический плюс. Я полагаю, если вы достаточно привержены этому, вы бы использовали факториальную таблицу (как реализовано).
Что я планировал после этого? локальное & | хранилище сеансов, чтобы обеспечить возможность кэширования необходимых итераций в каждом конкретном случае, по существу решая проблему "таблицы", о которой говорилось выше. Это также значительно сэкономит место на стороне базы данных и сервера. Однако, если вы выберете localStorage, вы, по сути, будете занимать место на своем компьютере пользователя, просто чтобы сохранить список чисел и заставить их экран СМОТРЕТЬ быстрее, однако в течение длительного периода времени с огромной потребностью это будет медленным. Я думаю, что sessionStorage (очистка после выхода вкладки) будет намного лучшим способом. Возможно ли совместить это с самобалансирующимся сервером / локальным зависимым кешем? Пользователю A нужно X итераций. Пользователю B нужно Y итераций. X + Y / 2 = сумма, необходимая для локального кеширования. Затем просто обнаруживайте и играйте с тестами времени загрузки и выполнения в реальном времени для каждого пользователя, пока он не настроится на оптимизацию для самого сайта. Благодарность!
Это редактирование реализует другое предложение стека и позволяет мне вызывать функцию как factorial (true) (5), что было одной из моих целей. : 3 Я также удалил некоторые ненужные присвоения и сократил некоторые закрытые имена переменных.
Отличная идея. Вместо того, чтобы дважды обходить длину, почему бы не преобразовать всю логику в функцию сокращения и не использовать ее начальное значение для обработки крайнего случая n === 0? Math.factorial = n => Array.from({ length: n }).reduce((product, _, i) => product * (i + 1), 1)
Ответы:
Вы можете искать (1 ... 100)! на Wolfram | Alpha для предварительного вычисления факториальной последовательности.
Первые 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
Если вы все еще хотите вычислить значения самостоятельно, вы можете использовать мемоизацию :
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; }
Изменить: 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);
Я предполагаю, что вы использовали бы какое-то закрытие, чтобы ограничить видимость имени переменной.
Ссылка : BigNumber Sandbox : JsFiddle
источник
function factorial (n) { for (var i = f.length; i <= n; i++) f.push(f[i - 1].multiply(i.toString())); return f[n]; }
увидеть также мой ответ, в котором используется более поздняя встроенная,BigInt
а не сторонняя библиотека.Вам следует использовать петлю.
Вот две версии, протестированные путем вычисления факториала 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; }
Жить в : http://jsfiddle.net/xMpTv/
Мои результаты показывают:
- Рекурсивный ~ 150 миллисекунд
- Итеративный ~ 5 миллисекунд ..
источник
rval = rval * i;
вас можно было написатьrval *= i;
Я по-прежнему считаю, что ответ Маргуса лучший. Однако, если вы хотите вычислить факториалы чисел в диапазоне от 0 до 1 (т.е. гамма-функцию), вы не можете использовать этот подход, потому что таблица поиска должна содержать бесконечные значения.
Однако вы можете аппроксимировать значения факториалов, и это довольно быстро, быстрее, чем рекурсивный вызов самого себя или, по крайней мере, цикл (особенно, когда значения начинают увеличиваться).
Хороший метод приближения - метод Ланцоша.
Вот реализация на 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)
и т. Д., Но точность может быть немного неточной, в конце концов, это приблизительное значение результата.источник
var d3d4 = Math.exp((z + 0.5) * Math.log(z + 5.5) - z - 5.5); return d1 * d2 * d3d4;
. Это позволяет вам вычислять факториалы до 169! вместо нынешних всего 140 !. Это довольно близко к максимально представимому факториалу с использованиемNumber
типа данных, который равен 170 !.Таблица поиска - очевидный путь, если вы работаете с натуральными числами. Чтобы вычислить любой факториал в реальном времени, вы можете ускорить его с помощью кеша, сохранив числа, которые вы вычисляли ранее. Что-то типа:
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; })();
Вы можете предварительно рассчитать некоторые значения, чтобы ускорить его еще больше.
источник
Вот мое решение:
function fac(n){ return(n<2)?1:fac(n-1)*n; }
Это самый простой способ (меньше символов / строк), который я нашел, только функция с одной строкой кода.
Изменить:
если вы действительно хотите сохранить несколько символов, вы можете использовать стрелки (21 байт) :
f=n=>(n<2)?1:f(n-1)*n
источник
f=n=>n?f(n-1)*n:1
...Всего одна линия с ES6
const factorial = n => !(n > 1) ? 1 : factorial(n - 1) * n;
Показать фрагмент кода
const factorial = n => !(n > 1) ? 1 : factorial(n - 1) * n; function print(value) { document.querySelector('.result').innerHTML = value; }
.result { margin-left: 10px; }
<input onkeyup="print(factorial(this.value))" type="number"/> <span class="result">......</span>
источник
factorial = n => n <= 1 ? 1 : factorial(n - 1) * n
короткая и простая рекурсивная функция (вы тоже можете сделать это с помощью цикла, но я не думаю, что это повлияет на производительность):
function factorial (n){ if (n==0 || n==1){ return 1; } return factorial(n-1)*n; }
для очень больших n вы можете использовать приближение Стиллингса, но это даст вам только приблизительное значение.
РЕДАКТИРОВАТЬ: комментарий о том, почему я получаю отрицательный голос за это, было бы неплохо ...
РЕДАКТИРОВАТЬ2: это было бы сутью с использованием цикла (что было бы лучшим выбором):
function factorial (n){ j = 1; for(i=1;i<=n;i++){ j = j*i; } return j; }
Я думаю , что лучшим решением было бы использовать кэшированные значения, как уже упоминалось Маргус и использовать приближение stirlings для больших значений (предполагается , что вы должны быть действительно быстро и не должны быть , что точно на таких больших чисел).
источник
Взгляните на мемоизатор, который принимает любую функцию с одним аргументом и запоминает ее. Оказывается, он немного быстрее, чем решение @ xPheRe , включая ограничение на размер кеша и связанную проверку, потому что я использую сокращение и так далее.
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; }());
Примерно в 25 раз быстрее на моей машине в Chrome, чем рекурсивная версия, и на 10% быстрее, чем у xPheRe.
источник
Самая быстрая факториальная функция
Я думаю, что эта версия на основе цикла может быть самой быстрой факториальной функцией.
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)
n
иr
, поэтому теоретически меньше параметров означает меньше времени, затрачиваемого на выделение памяти.n
равно ли нулю - я слышал теории о том, что компьютеры лучше проверяют двоичные числа (0 и 1), чем другие целые числа.источник
Я наткнулся на этот пост. Вдохновленный всеми представленными здесь материалами, я придумал свою собственную версию, в которой есть две функции, которые я раньше не видел: 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) должен присутствовать, иначе он сломается.
Наслаждаться :)
источник
Использовать ES6 очень просто
const factorial = n => n ? (n * factorial(n-1)) : 1;
См. Пример здесь
источник
Вот одно из решений:
function factorial(number) { total = 1 while (number > 0) { total *= number number = number - 1 } return total }
источник
Используя ES6, вы можете добиться этого быстро и быстро:
const factorial = n => [...Array(n + 1).keys()].slice(1).reduce((acc, cur) => acc * cur, 1)
источник
Код для вычисления факториала зависит от ваших требований.
Что касается пунктов 1 и 4, часто бывает более полезно иметь функцию для оценки журнала факториала напрямую, чем иметь функцию для оценки самого факториала.
Вот сообщение в блоге, в котором обсуждаются эти проблемы. Вот некоторый код C # для вычисления лог-факториала, который было бы тривиально перенести на JavaScript. Но это может не подходить для ваших нужд в зависимости от ваших ответов на вопросы выше.
источник
Это компактная версия на основе петель
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 ) ; }
Или присоединитесь к обоим подходам ...
источник
Воспользовавшись тем фактом, что
Number.MAX_VALUE < 171!
мы можем просто использовать полную таблицу поиска, состоящую всего из 171 элемента компактного массива, занимающего менее 1,4 килобайт памяти.Тогда функция быстрого поиска со сложностью выполнения O (1) и минимальными накладными расходами на доступ к массиву будет выглядеть следующим образом:
// 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
Это так же точно и быстро, как и при использовании
Number
типа данных. Вычисление таблицы поиска в Javascript - как предлагают некоторые другие ответы - снизит точность, когдаn! > Number.MAX_SAFE_INTEGER
.Сжатие таблицы времени выполнения с помощью gzip уменьшает ее размер на диске примерно с 3,6 до 1,8 килобайт.
источник
Однострочный ответ:
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
источник
Итерационный факториал с
BigInt
для безопасностиЭто рабочий пример использования
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
тип.BigInt
с,Number
если вы явно не принуждаете их, и это может привести к потере точности.источник
Используя функции ES6, можно писать код в ОДНОЙ строке и без рекурсии :
var factorial=(n)=>Array.from({length: n},(v, k) => k+1).reduce((a, b) => a*b, 1)
Показать фрагмент кода
var factorial=(n)=>Array.from( {length: n}, (v, k) => k+1) /*Generate Array [1, 2, .., n -1, n]*/ .reduce( (a, b) => a*b, 1 /*Multiply all aarray items; one with the next*/ ); var n = prompt('Give us "n", we will calculate "n!" ?'); if (n) { alert(`${n}! = ${factorial(n)}`) }
источник
Просто для полноты, вот рекурсивная версия, которая позволяет оптимизировать хвостовой вызов. Я не уверен, что оптимизация хвостовых вызовов выполняется в 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, который является литералом объекта, поэтому прототипа нет. Скорее просто привязывайте их к функции напрямую.
источник
Math.factorial(100); Math.factorial(500);
дважды вычисляет умножение 1..100.Я считаю, что следующий фрагмент кода является наиболее устойчивым и эффективным из приведенных выше комментариев. Вы можете использовать это в своей глобальной архитектуре js приложения ... и не беспокойтесь о том, чтобы писать его в нескольких пространствах имен (поскольку это задача, которая, вероятно, не требует значительного дополнения). Я включил два имени метода (в зависимости от предпочтений), но оба могут использоваться, поскольку они просто ссылки.
Math.factorial = Math.fact = function(n) { if (isNaN(n)||n<0) return undefined; var f = 1; while (n > 1) { f *= n--; } return f; };
источник
n * (n-1) * (n-2) * ... * 1
вместо наоборот, вы потеряете до 4 цифр в точности для n >> 20.// 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 значений на лету и не вводит внешнюю переменную в область действия кеша, сохраняя значения как свойства самого объекта функции, что означает, что, если вы знаете,
factorial(n)
что уже вычислено, вы можете просто назовите егоfactorial[n]
, что немного эффективнее. Запуск этих первых 100 значений в современных браузерах займет менее миллисекунды.источник
21! > Number.MAX_SAFE_INTEGER
, что , таким образом, его нельзя безопасно представить как 64-битное число с плавающей запятой.Вот реализация, которая вычисляет как положительные, так и отрицательные факториалы. Это быстро и просто.
var factorial = function(n) { return n > 1 ? n * factorial(n - 1) : n < 0 ? n * factorial(n + 1) : 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; }
источник
i
и выполняет слишком многоNumber
преобразований и дает неверные результаты для 0! (как вы сказали, но почему?).Вот мой код
function factorial(num){ var result = num; for(i=num;i>=2;i--){ result = result * (i-1); } return result; }
источник
factorial(0)
. Кроме того, начав умножение с n * (n-1) * (n-2) * ... * 1, а не наоборот, вы потеряете до 4 цифр в точности для n >> 20. @prime:170! > Number.MAX_VALUE
и лучше всего представлен с помощьюInfinity
.Кешированный цикл должен быть самым быстрым (по крайней мере, при многократном вызове)
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 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; });
Изучив ввод от других участников (за исключением рекомендаций журнала, хотя я могу реализовать это позже), я пошел дальше и составил довольно простой сценарий. Я начал с простого необразованного примера ООП на JavaScript и построил небольшой класс для обработки факториалов. Затем я реализовал свою версию мемоизации, предложенную выше. Я также реализовал сокращенную факториализацию, но сделал небольшую корректировку ошибок; Я изменил «n <2» на «n <3». «n <2» по-прежнему будет обрабатывать n = 2, что было бы пустой тратой, потому что вы бы выполняли итерацию для 2 * 1 = 2; на мой взгляд, это бесполезная трата. Я изменил его на «n <3»; потому что, если n равно 1 или 2, он просто вернет n, если он равен 3 или более, он будет оцениваться нормально. Конечно, поскольку применяются правила, я разместил свои функции в порядке убывания предполагаемого выполнения. Я добавил опцию bool (true | false), чтобы разрешить быстрое переключение между memo'ed и нормальным выполнением (вы просто никогда не знаете, когда вы захотите поменять местами на своей странице, не изменяя «стиль»). Как я уже говорил перед Переменная memoized factorials задается с 3 начальными позициями, принимает 4 символа и сводит к минимуму бесполезные вычисления. После третьей итерации вы обрабатываете двузначный математический плюс. Я полагаю, если вы достаточно привержены этому, вы бы использовали факториальную таблицу (как реализовано). взяв 4 символа и минимизируя бесполезные вычисления. После третьей итерации вы обрабатываете двузначный математический плюс. Я полагаю, если вы достаточно привержены этому, вы бы использовали факториальную таблицу (как реализовано). взяв 4 символа и минимизируя бесполезные вычисления. После третьей итерации вы обрабатываете двузначный математический плюс. Я полагаю, если вы достаточно привержены этому, вы бы использовали факториальную таблицу (как реализовано).
Что я планировал после этого? локальное & | хранилище сеансов, чтобы обеспечить возможность кэширования необходимых итераций в каждом конкретном случае, по существу решая проблему "таблицы", о которой говорилось выше. Это также значительно сэкономит место на стороне базы данных и сервера. Однако, если вы выберете localStorage, вы, по сути, будете занимать место на своем компьютере пользователя, просто чтобы сохранить список чисел и заставить их экран СМОТРЕТЬ быстрее, однако в течение длительного периода времени с огромной потребностью это будет медленным. Я думаю, что sessionStorage (очистка после выхода вкладки) будет намного лучшим способом. Возможно ли совместить это с самобалансирующимся сервером / локальным зависимым кешем? Пользователю 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); });
источник
undefined
за 0 !. ES6 позволяет заменитьisNumeric
наNumber.isInteger
. Строки вродеfactorials[0][factorials[1]]=factorials[0][factorial_index]*(factorials[1]+1);
совершенно нечитаемы.Вот один, использующий новые функции javascript fill , map , reduce и конструктор (и синтаксис жирной стрелки):
Math.factorial = n => n === 0 ? 1 : Array(n).fill(null).map((e,i)=>i+1).reduce((p,c)=>p*c)
Изменить: обновлено для обработки n === 0
источник
n === 0
?Math.factorial = n => Array.from({ length: n }).reduce((product, _, i) => product * (i + 1), 1)
function computeFactorialOfN(n) { var output=1; for(i=1; i<=n; i++){ output*=i; } return output; } computeFactorialOfN(5);
источник