Алгоритмы быстрого вычисления факториала
Время на прочтение
6 мин
Количество просмотров 209K
Понятие факториала известно всем. Это функция, вычисляющая произведение последовательных натуральных чисел от 1 до N включительно: N! = 1 * 2 * 3 *… * N. Факториал — быстрорастущая функция, уже для небольших значений N значение N! имеет много значащих цифр.
Попробуем реализовать эту функцию на языке программирования. Очевидно, нам понадобиться язык, поддерживающий длинную арифметику. Я воспользуюсь C#, но с таким же успехом можно взять Java или Python.
Наивный алгоритм
Итак, простейшая реализация (назовем ее наивной) получается прямо из определения факториала:
static BigInteger FactNaive(int n)
{
BigInteger r = 1;
for (int i = 2; i <= n; ++i)
r *= i;
return r;
}
На моей машине эта реализация работает примерно 1,6 секунд для N=50 000.
Далее рассмотрим алгоритмы, которые работают намного быстрее наивной реализации.
Алгоритм вычисления деревом
Первый алгоритм основан на том соображении, что длинные числа примерно одинаковой длины умножать эффективнее, чем длинное число умножать на короткое (как в наивной реализации). То есть нам нужно добиться, чтобы при вычислении факториала множители постоянно были примерно одинаковой длины.
Пусть нам нужно найти произведение последовательных чисел от L до R, обозначим его как P(L, R). Разделим интервал от L до R пополам и посчитаем P(L, R) как P(L, M) * P(M + 1, R), где M находится посередине между L и R, M = (L + R) / 2. Заметим, что множители будут примерно одинаковой длины. Аналогично разобьем P(L, M) и P(M + 1, R). Будем производить эту операцию, пока в каждом интервале останется не более двух множителей. Очевидно, что P(L, R) = L, если L и R равны, и P(L, R) = L * R, если L и R отличаются на единицу. Чтобы найти N! нужно посчитать P(2, N).
Посмотрим, как будет работать наш алгоритм для N=10, найдем P(2, 10):
P(2, 10)
P(2, 6) * P(7, 10)
( P(2, 4) * P(5, 6) ) * ( P(7, * P(9, 10) )
( (P(2, 3) * P(4) ) * P(5, 6) ) * ( P(7, * P(9, 10) )
( ( (2 * 3) * (4) ) * (5 * 6) ) * ( (7 * * (9 * 10) )
( ( 6 * 4 ) * 30 ) * ( 56 * 90 )
( 24 * 30 ) * ( 5 040 )
720 * 5 040
3 628 800
Получается своеобразное дерево, где множители находятся в узлах, а результат получается в корне
Реализуем описанный алгоритм:
static BigInteger ProdTree(int l, int r)
{
if (l > r)
return 1;
if (l == r)
return l;
if (r - l == 1)
return (BigInteger)l * r;
int m = (l + r) / 2;
return ProdTree(l, m) * ProdTree(m + 1, r);
}
static BigInteger FactTree(int n)
{
if (n < 0)
return 0;
if (n == 0)
return 1;
if (n == 1 || n == 2)
return n;
return ProdTree(2, n);
}
Для N=50 000 факториал вычисляется за 0,9 секунд, что почти вдвое быстрее, чем в наивной реализации.
Алгоритм вычисления факторизацией
Второй алгоритм быстрого вычисления использует разложение факториала на простые множители (факторизацию). Очевидно, что в разложении N! участвуют только простые множители от 2 до N. Попробуем посчитать, сколько раз простой множитель K содержится в N!, то есть узнаем степень множителя K в разложении. Каждый K-ый член произведения 1 * 2 * 3 *… * N увеличивает показатель на единицу, то есть показатель степени будет равен N / K. Но каждый K2-ый член увеличивает степень еще на единицу, то есть показатель становится N / K + N / K2. Аналогично для K3, K4 и так далее. В итоге получим, что показатель степени при простом множителе K будет равен N / K + N / K2 + N / K3 + N / K4 +…
Для наглядности посчитаем, сколько раз двойка содержится в 10! Двойку дает каждый второй множитель (2, 4, 6, 8 и 10), всего таких множителей 10 / 2 = 5. Каждый четвертый дает четверку (22), всего таких множителей 10 / 4 = 2 (4 и 8). Каждый восьмой дает восьмерку (23), такой множитель всего один 10 / 8 = 1 (8). Шестнадцать (24) и более уже не дает ни один множитель, значит, подсчет можно завершать. Суммируя, получим, что показатель степени при двойке в разложении 10! на простые множители будет равен 10 / 2 + 10 / 4 + 10 / 8 = 5 + 2 + 1 = 8.
Если действовать таким же образом, можно найти показатели при 3, 5 и 7 в разложении 10!, после чего остается только вычислить значение произведения:
10! = 28 * 34 * 52 * 71 = 3 628 800
Осталось найти простые числа от 2 до N, для этого можно использовать решето Эратосфена:
static BigInteger FactFactor(int n)
{
if (n < 0)
return 0;
if (n == 0)
return 1;
if (n == 1 || n == 2)
return n;
bool[] u = new bool[n + 1]; // маркеры для решета Эратосфена
List<Tuple<int, int>> p = new List<Tuple<int, int>>(); // множители и их показатели степеней
for (int i = 2; i <= n; ++i)
if (!u[i]) // если i - очередное простое число
{
// считаем показатель степени в разложении
int k = n / i;
int c = 0;
while (k > 0)
{
c += k;
k /= i;
}
// запоминаем множитель и его показатель степени
p.Add(new Tuple<int, int>(i, c));
// просеиваем составные числа через решето
int j = 2;
while (i * j <= n)
{
u[i * j] = true;
++j;
}
}
// вычисляем факториал
BigInteger r = 1;
for (int i = p.Count() - 1; i >= 0; --i)
r *= BigInteger.Pow(p[i].Item1, p[i].Item2);
return r;
}
Эта реализация также тратит примерно 0,9 секунд на вычисление 50 000!
Библиотека GMP
Как справедливо отметил
pomme скорость вычисления факториала на 98% зависит от скорости умножения. Попробуем протестировать наши алгоритмы, реализовав их на C++ с использованием библиотеки GMP. Результаты тестирования приведены ниже, по ним получается что алгоритм умножения в C# имеет довольно странную асимптотику, поэтому оптимизация дает относительно небольшой выигрыш в C# и огромный в C++ с GMP. Однако этому вопросу вероятно стоит посвятить отдельную статью.
Сравнение производительности
Все алгоритмы тестировались для N равном 1 000, 2 000, 5 000, 10 000, 20 000, 50 000 и 100 000 десятью итерациями. В таблице указано среднее значение времени работы в миллисекундах.
График с линейной шкалой
График с логарифмической шкалой
Идеи и алгоритмы из комментариев
Хабражители предложили немало интересных идей и алгоритмов в ответ на мою статью, здесь я оставлю ссылки на лучшие из них
lany распараллелил дерево на Java с помощью Stream API и получил ускорение в 18 раз
Mrrl предложил оптимизацию факторизации на 15-20%
PsyHaSTe предложил улучшение наивной реализации
Krypt предложил распараллеленную версию на C#
SemenovVV предложил реализацию на Go
pomme предложил использовать GMP
ShashkovS предложил быстрый алгоритм на Python
Исходные коды
Исходные коды реализованных алгоритмов приведены под спойлерами
C#
using System;
using System.Linq;
using System.Text;
using System.Numerics;
using System.Collections.Generic;
using System.Collections.Specialized;
namespace BigInt
{
class Program
{
static BigInteger FactNaive(int n)
{
BigInteger r = 1;
for (int i = 2; i <= n; ++i)
r *= i;
return r;
}
static BigInteger ProdTree(int l, int r)
{
if (l > r)
return 1;
if (l == r)
return l;
if (r - l == 1)
return (BigInteger)l * r;
int m = (l + r) / 2;
return ProdTree(l, m) * ProdTree(m + 1, r);
}
static BigInteger FactTree(int n)
{
if (n < 0)
return 0;
if (n == 0)
return 1;
if (n == 1 || n == 2)
return n;
return ProdTree(2, n);
}
static BigInteger FactFactor(int n)
{
if (n < 0)
return 0;
if (n == 0)
return 1;
if (n == 1 || n == 2)
return n;
bool[] u = new bool[n + 1];
List<Tuple<int, int>> p = new List<Tuple<int, int>>();
for (int i = 2; i <= n; ++i)
if (!u[i])
{
int k = n / i;
int c = 0;
while (k > 0)
{
c += k;
k /= i;
}
p.Add(new Tuple<int, int>(i, c));
int j = 2;
while (i * j <= n)
{
u[i * j] = true;
++j;
}
}
BigInteger r = 1;
for (int i = p.Count() - 1; i >= 0; --i)
r *= BigInteger.Pow(p[i].Item1, p[i].Item2);
return r;
}
static void Main(string[] args)
{
int n;
int t;
Console.Write("n = ");
n = Convert.ToInt32(Console.ReadLine());
t = Environment.TickCount;
BigInteger fn = FactNaive(n);
Console.WriteLine("Naive time: {0} ms", Environment.TickCount - t);
t = Environment.TickCount;
BigInteger ft = FactTree(n);
Console.WriteLine("Tree time: {0} ms", Environment.TickCount - t);
t = Environment.TickCount;
BigInteger ff = FactFactor(n);
Console.WriteLine("Factor time: {0} ms", Environment.TickCount - t);
Console.WriteLine("Check: {0}", fn == ft && ft == ff ? "ok" : "fail");
}
}
}
C++ с GMP
#include <iostream>
#include <ctime>
#include <vector>
#include <utility>
#include <gmpxx.h>
using namespace std;
mpz_class FactNaive(int n)
{
mpz_class r = 1;
for (int i = 2; i <= n; ++i)
r *= i;
return r;
}
mpz_class ProdTree(int l, int r)
{
if (l > r)
return 1;
if (l == r)
return l;
if (r - l == 1)
return (mpz_class)r * l;
int m = (l + r) / 2;
return ProdTree(l, m) * ProdTree(m + 1, r);
}
mpz_class FactTree(int n)
{
if (n < 0)
return 0;
if (n == 0)
return 1;
if (n == 1 || n == 2)
return n;
return ProdTree(2, n);
}
mpz_class FactFactor(int n)
{
if (n < 0)
return 0;
if (n == 0)
return 1;
if (n == 1 || n == 2)
return n;
vector<bool> u(n + 1, false);
vector<pair<int, int> > p;
for (int i = 2; i <= n; ++i)
if (!u[i])
{
int k = n / i;
int c = 0;
while (k > 0)
{
c += k;
k /= i;
}
p.push_back(make_pair(i, c));
int j = 2;
while (i * j <= n)
{
u[i * j] = true;
++j;
}
}
mpz_class r = 1;
for (int i = p.size() - 1; i >= 0; --i)
{
mpz_class w;
mpz_pow_ui(w.get_mpz_t(), mpz_class(p[i].first).get_mpz_t(), p[i].second);
r *= w;
}
return r;
}
mpz_class FactNative(int n)
{
mpz_class r;
mpz_fac_ui(r.get_mpz_t(), n);
return r;
}
int main()
{
int n;
unsigned int t;
cout << "n = ";
cin >> n;
t = clock();
mpz_class fn = FactNaive(n);
cout << "Naive: " << (clock() - t) * 1000 / CLOCKS_PER_SEC << " ms" << endl;
t = clock();
mpz_class ft = FactTree(n);
cout << "Tree: " << (clock() - t) * 1000 / CLOCKS_PER_SEC << " ms" << endl;
t = clock();
mpz_class ff = FactFactor(n);
cout << "Factor: " << (clock() - t) * 1000 / CLOCKS_PER_SEC << " ms" << endl;
t = clock();
mpz_class fz = FactNative(n);
cout << "Native: " << (clock() - t) * 1000 / CLOCKS_PER_SEC << " ms" << endl;
cout << "Check: " << (fn == ft && ft == ff && ff == fz ? "ok" : "fail") << endl;
return 0;
}
#статьи
- 19 май 2023
-
0
Что такое факториал и как его вычислить
Статья, после которой вы начнёте щёлкать факториалы как орешки.
Иллюстрация: Катя Павловская для Skillbox Media
Любитель научной фантастики и технологического прогресса. Хорошо сочетает в себе заумного технаря и утончённого гуманитария. Пишет про IT и радуется этому.
Даже если вы уже давно окончили школу, факториалы всё равно могут доставить немало приятных флешбэков — например, если вы обучаетесь программированию и знакомитесь с задачками на рекурсию или комбинаторику. Поэтому мы решили максимально просто объяснить, что такое факториал, как его вычислять и зачем он вообще нужен.
Эта статья будет полезна как опытным программистам, которые хотят освежить знания, так и тем, кто ещё учится: школьникам, студентам и совсем зелёным джунам.
Содержание:
- Что такое факториал
- Для чего он нужен
- Основные свойства и формулы
- Шпаргалка: таблица факториалов
- Решаем задачи на факториалы
- Что запомнить
Факториал числа n — это произведение всех натуральных чисел от единицы до n. Обозначается факториал символом восклицательного знака: !.
Это определение из учебника, и оно пока звучит сложновато — неясно, зачем эти факториалы вообще нужны и как они могут пригодиться в науке и технике. Но об этом чуть позже — для начала давайте посмотрим на примеры факториалов:
Чтобы вычислить их, нам нужно перемножить все числа от единицы до числа, стоящего под знаком факториала — так гласит определение. Получаем выражения:
Ещё в математическом определении сказано, что факториал не может быть отрицательным или дробным — то есть вот такие факториалы вычислить нельзя:
Факториалы незаменимы там, где нужно быстро посчитать количество комбинаций и сочетаний разных предметов. В математике этому посвящён даже целый раздел — комбинаторика. Её методы используют много где: от лингвистики до криптографии и анализа ДНК. И во всех этих сферах факториал помогает упрощать сложные вычисления.
Разберём на примере, как это работает.
Допустим, у вас есть пять шоколадок и вы решили раздать их пяти друзьям — каждому по одной. Задача — выяснить, сколько существует способов раздать эти шоколадки. Начинаем размышлять:
- первую шоколадку можно отдать одному из пяти друзей;
- вторую — одному из четырёх друзей, потому что один уже получил свою шоколадку;
- третью — одному из трёх, потому что двое уже наслаждаются своими шоколадками;
- четвёртую — одному из двух;
- пятую — последнему другу.
Получается, что способов раздать первую шоколадку — 5, вторую — 4, третью — 3, четвёртую — 2, а пятую — всего 1. По правилам математики, чтобы выяснить общее количество всех вариантов, нужно перемножить их между собой. Ну а кто мы такие, чтобы с этими правилами спорить?
Смотрим на выражение выше и понимаем: ведь оно идеально вписывается в определение факториала — произведение натуральных чисел от одного до n (в нашем случае n равно 5). Следовательно, это выражение можно коротко и изящно записать в виде факториала:
Выходит, что всего способов раздать пять шоколадок пяти друзьям существует 120. Вот как может выглядеть один из них:
Конечно, в жизни вам вряд ли придётся считать количество способов раздать друзьям шоколадки. Но, например, в статистике, теории вероятностей, матанализе и программировании факториалы используют сплошь и рядом. Так что, если видите себя в будущем на матмехе или, на худой конец, в IT, то лучше познакомиться с ними хотя бы бегло.
Так как факториалы используются в разных областях математики, свойств у них довольно много — каждая область привносит какие-то свои методы вычислений. Одно из свойств вы уже знаете: факториал — это всегда целое положительное число. Вот ещё несколько, которые стоит запомнить:
- Факториал нуля равен единице — 0! = 1.
- Факториал единицы тоже равен единице: 1! = 1.
- Рекурсия: n! = (n – 1)! × n. Это основное свойство факториалов, о нём мы чуть подробнее поговорим дальше.
Мы видим, что каждое свойство описывается какой-то формулой — и некоторые из этих формул могут быть весьма полезны. Они позволяют нам находить факториалы проще и быстрее, чем простым перемножением натуральных чисел. Разберём эти формулы тоже.
Чтобы вычислить факториал, не используя так много операций умножения, придумали формулу Стирлинга. Вот как она выглядит:
Выглядит страшно, но на самом деле она очень полезная. Её используют, когда хотят приблизительно узнать факториал большого числа. Обычным способом это будет сделать сложно даже мощному компьютеру — например, попробуйте посчитать в онлайн-калькуляторе факториал числа 10 024 (спойлер: это может занять несколько часов и даже дней).
Скришнот: «Контрольная работа РУ — калькуляторы онлайн» / Skillbox Media
Давайте попробуем вычислить факториал числа 6 по этой формуле:
Число e примерно равно 2,71, а π — 3,14. Подставляем их в выражение и получаем ответ:
Получили приближённое значение настоящего факториала, который равен 720. Но можно сделать ответ и более точным. Для этого нужно добавить больше знаков после запятой всем переменным — например, если взять 20 знаков, то ответ будет таким:
Это уже больше похоже на правду. Хотя погрешность всё равно есть.
Рекуррентная формула позволяет вычислить факториал числа n, основываясь на факториале предыдущего числа — (n – 1). Выглядит она так:
В целом рекуррентная формула не приносит нам большой пользы, так как всё равно приходится вычислять факториал предыдущего числа. Если он равен какому-то большому числу (например, 100), то использование формулы теряет смысл — слишком уж много вычислений это потребует.
Рекуррентная формула основана на главном свойстве факториалов — рекурсии: n! = (n – 1)! × n. Это свойство особенно полезно при решении задач по комбинаторике: так мы можем быстро сокращать факториалы и упрощать выражения.
Однако рекуррентная формула хорошо подходит для алгоритмов — в частности, для программирования. Мы можем задать начальное значение: например, что 0! = 1 или 1! = 1, а затем считать следующие факториалы по формуле:
Получим алгоритм для вычисления факториалов. Не очень эффективный, но простой.
Давайте вычислим по этой формуле факториал числа 4. Сначала распишем рекуррентную формулу до базового значения — факториала числа 1:
Можно записать это и в сокращённом виде:
Теперь последовательно подставляем значение факториала, которое мы уже знаем, и вычисляем результат:
Получили ответ — 24. Ничего сложного, просто перемножаем числа.
Кстати, всю эту формулу можно обернуть в реально работающую функцию на языке Python:
def factorial(n): # Определяем функцию if n == 0 or n == 1: # Базовый случай return 1 else: # Рекуррентный случай return factorial(n-1) * n # Вызываем эту же функцию, но с меньшим аргументом print(factorial(4)) # Печатаем факториал 4 # Вывод: # 24
Можете попробовать запустить её в онлайн-интерпретаторе и посмотреть, как работает. Тут есть один нюанс: Python не даст вам посчитать факториал числа больше 998, так как у него есть ограничение на количество вызовов функции — в программировании это называется глубиной рекурсии.
Чтобы быстро находить, чему равен факториал, можно запомнить или сохранить в заметки вот такую табличку. Она рассчитана всего на 12 чисел, но для большинства учебных задач этого хватит.
1! | 1 |
2! | 2 |
3! | 6 |
4! | 24 |
5! | 120 |
6! | 720 |
7! | 5040 |
8! | 40 320 |
9! | 362 880 |
10! | 3 628 800 |
11! | 39 916 800 |
12! | 479 001 600 |
С теорией вроде разобрались — теперь попробуем решить несколько задач с факториалами, чтобы закрепить знания на практике.
Задача: перемножить два факториала.
Решение:
Сперва нужно вычислить значения факториалов, а затем перемножить полученные значения:
Обратите внимание: во второй строке мы применили рекуррентную формулу, чтобы быстрее вычислить факториал числа 7.
Задача: вычесть из одного факториала другой.
Решение:
Используем тот же подход, что и в предыдущей задаче: сначала вычисляем факториалы, а затем получаем ответ на всё выражение.
Вроде бы ничего сложного, главное — не запутаться в умножении.
Задача: умножить один факториал на другой:
Решение:
Вычисляем факториалы, потом перемножаем их значения:
Во второй строке мы воспользовались таблицей выше и быстро нашли значение факториала от числа 8.
Задача: сократить дробь и вычислить её значение.
Решение:
Здесь мы воспользуемся рекуррентной формулой для вычисления факториала и разложим верхний факториал на множители:
В первой строке мы применили рекуррентную формулу два раза, а во второй — просто сократили одинаковые факториалы в числителе и в знаменателе.
Задача: сократить дробь.
Решение:
Хотя здесь нет конкретных чисел, но принцип решения остаётся таким же: используем рекуррентную формулу и сокращаем одинаковые значения в числителе и знаменателе.
Главное — не запутаться и правильно применить рекуррентную формулу.
- Факториал — это произведение всех натуральных чисел от 1 до данного числа. Например, факториал числа 5 будет равен 1 × 2 × 3 × 4 × 5 = 120.
- Его используют во многих областях науки — например, комбинаторике, теории вероятностей и математическом анализе.
- Помимо стандартной формулы для вычисления факториала можно использовать формулы Стирлинга и рекуррентную формулу.
- Формула Стирлинга нужна для того, чтобы посчитать факториал без большого числа операций умножения.
- Рекуррентная формула позволяет вычислить факториал на основе предыдущего факториала.
Научитесь: Профессия Data Scientist
Узнать больше
Ирина Песцова
Эксперт по предмету «Информатика»
Задать вопрос автору статьи
Определение 1
Алгоритмы для вычисления факториала — это алгоритм определения произведения всех натуральных чисел, начиная от единицы и до заданного числа включительно.
Под термином факториал числа понимается функция, которая вычисляет произведение последовательности натуральных чисел от единицы до N включительно: N! = 1 • 2 • 3 • … • N. Факториал является очень быстро увеличивающейся функцией, поскольку даже при относительно малых по величине N, значение его факториала будет уже многоразрядным. Рассмотрим некоторые алгоритмы, позволяющие вычислить факториал числа.
Наивный алгоритм
Этот алгоритм является самой простой реализацией, так как просто выполняет действия, заложенные в определении факториала:
Сдай на права пока
учишься в ВУЗе
Вся теория в удобном приложении. Выбери инструктора и начни заниматься!
Получить скидку 3 000 ₽
Рисунок 1. Наивный алгоритм. Автор24 — интернет-биржа студенческих работ
Эта программа выполняется за интервал времени менее двух секунд для N до пятидесяти тысяч. Но есть и более продвинутые алгоритмы и один из них рассмотрим далее.
Алгоритм вычисления деревом
Этот алгоритм базируется на таком положении, что операция умножения с числами большой и примерно одинаковой разрядности будет эффективнее умножения большого числа на маленькое. Исходя из этого, необходимо обеспечить при определении факториала примерно равный размер сомножителей на постоянной основе. Пускай требуется вычислить произведение последовательности чисел от L до R. Введём обозначение этого произведения как Р (L, R). Поделим промежуток между L и R на два и вычислим Р (L, R) как P(L, M) • P(M + 1, R), здесь M является серединой чисел L и R, то есть M = (L + R) / 2. Следует отметить, что сомножители получаются примерно одинаковыми. Затем по аналогии разбиваем далее P(L, M) и P(M + 1, R). Эту процедуру необходимо выполнять до тех пор, пока каждый интервал не будет иметь больше двух сомножителей. Понятно, что Р (L, R) = L, когда L и R равны, и P(L, R) = L • R, если L и R имеют единичное отличи. Для того, чтобы вычислить N!, требуется определить Р(2, N). Рассмотрим действие этого алгоритма для N=10, определим Р (2, 10):
«Алгоритмы для вычисления факториала» 👇
P(2, 10)
P(2, 6) • P(7, 10)
( P(2, 4) • P(5, 6) ) • ( P(7, • P(9, 10) )
( (P(2, 3) • P(4) ) • P(5, 6) ) • ( P(7, • P(9, 10) )
( ( (2 • 3) • (4) ) • (5 • 6) ) • ( (7 • • (9 • 10) )
( ( 6 • 4 ) • 30 ) • ( 56 • 90 )
( 24 • 30 ) • ( 5 040 )
720 • 5 040
3 628 800
В итоге мы получили подобие дерева, у которого сомножители расположены в узлах, а результирующее значение находится в корневой системе.
Рисунок 2. Дерево. Автор24 — интернет-биржа студенческих работ
Программная реализация этого алгоритма приведена ниже:
Рисунок 3. Программа. Автор24 — интернет-биржа студенческих работ
По этой программе для числа пятьдесят тысяч вычисление факториала длится менее секунды, что в два раза быстрее предыдущего алгоритма.
Алгоритм вычисления факторизацией
Данный алгоритм способен разложить факториал на простые сомножители, что и есть по сути факторизация. То есть в преобразовании N! принимают участие только простые сомножители от двух до N. Вычислим количество вложений сомножителя К в факториал N!. Или иначе, определим в какой степени стоит сомножитель К в этом разложении. Каждый К-ый сомножитель произведения 1 • 2 • 3 • … • N приводит к возрастанию степени на единицу, то есть степень равняется N / K. Далее учитываем, что K в квадрате компонент также даёт возрастание степени на единицу, то есть показатель степени будет $N / K+ N / K^2$
Далее с возрастанием степени будет такая же картина. В финале имеем следующую формулу для показателя степени простого сомножителя К:
$N / K+ N / K^2 + N / K^3 + N / K^4 +…$
Для примера определим, сколько раз двойка в различных степенях входит в факториал десяти. Число два содержится в каждом втором сомножителе (2, 4, 6, 8 и 10). А общее число этих сомножителей 10 / 2 = 5. При этом, каждый четвёртый множитель выдаёт число четыре (то есть два в степени два). Этих сомножителей 10 / 4 = 2 (4 и 8). Далее восьмой сомножитель даёт число восемь (то есть два в степени три). Такой сомножитель только один 10 / 8 = 1 (8). Два в четвёртой степени — это число шестнадцать. Но его нет ни в одном сомножителе, следовательно, алгоритм можно останавливать. В итоге видим, что степень числа два при разложении факториала десяти на простые сомножители равняется 10 / 2 + 10 / 4 + 10 / 8 = 5 + 2 + 1 = 8.
Аналогично возможно определить показатели степени других простых сомножителей в факториале десяти (это числа три, пять и семь). Затем уже можно определить их произведение: $10! = 2^8 • 3^4 • 5^2 • 7^1 = 3 628 800$.
Находи статьи и создавай свой список литературы по ГОСТу
Поиск по теме
A factorial is a mathematical operation that you write like this: n!
. It represents the multiplication of all numbers between 1 and n.
So if you were to have 3!
, for example, you’d compute 3 x 2 x 1 (which = 6). Let’s see how it works with some more examples.
Definition of a Factorial
The factorial of a number is the multiplication of all the numbers between 1 and the number itself. It is written like this: n!
. So the factorial of 2 is 2!
(= 1 × 2).
To calculate a factorial you need to know two things:
0! = 1
n! = (n - 1)! × n
The factorial of 0 has value of 1, and the factorial of a number n
is equal to the multiplication between the number n
and the factorial of n-1
.
For example, 5!
is equal to 4! × 5
.
Here the first few factorial values to give you an idea of how this works:
Factorial | Multiplication | Result |
---|---|---|
0! | 1 | 1 |
1! | 1 | 1 |
2! | 1 × 2 | 2 |
3! | 1 × 2 × 3 | 6 |
4! | 1 × 2 × 3 × 4 | 24 |
5! | 1 × 2 × 3 × 4 × 5 | 120 |
6! | 1 × 2 × 3 × 4 × 5 × 6 | 720 |
7! | 1 × 2 × 3 × 4 × 5 × 6 × 7 | 5040 |
8! | 1 × 2 × 3 × 4 × 5 × 6 × 7 × 8 | 40,320 |
9! | 1 × 2 × 3 × 4 × 5 × 6 × 7 × 8 × 9 | 362,880 |
What is a Factorial Used For?
Practically speaking, a factorial is the number of different permutations you can have with n
items: 3 items can be arranged in exactly 6 different ways (expressed as 3!
).
For example, let’s see all the arrangements you can have with the three items, A, B and C:
ABC
ACB
BAC
BCA
CAB
CBA
And in fact, 3! = 6
.
How to Calculate the Factorial of 0
Looking at the factorial from this point of view, what’s the factorial of 0?
Well, how many different ways can you arrange 0 elements?
There is exactly 1 way to arrange zero elements. And that’s making a sequence of zero elements.
Factorial Use Cases
You typically use a factorial when you have a problem related to the number of possible arrangements. Let’s look at some example problems.
Factorial example problem 1: the letters in the word «camper»
How many different ways can you arrange the letters of the word camper
?
The word camper
has 6 letters, so the number of possible arrangements is given by the factorial of 6: 6! = 6 × 5 × 4 × 3 × 2 × 1 = 720
. That would have been a pretty big number of arrangements to find by hand, wouldn’t it?
Factorial example problem 2: drawing colored balls from a bag
Let’s say there are three balls in a bag – one green, one blue, and one yellow.
If you draw the three balls in sequence, what chance is there that you’ll get the yellow first, the green one second, and the blue one last?
Maybe now you are wondering what chances have to do with factorials – well, in a moment you will see.
There are 6 possible sequences in which the balls can be drawn: 3! = 6.
There is a chance of 1 over the total number of possibilities to get the yellow-green-blue sequence, so that is 1/(3!)
or 1/6
or 16.7%
chance to get the desired outcome.
How to Calculate a Factorial Programmatically with JavaScript
There are two ways to calculate factorials programmatically in JavaScript:
How to calculate a factorial in JS with recursion
Let’s get back to the two things to know when calculating a factorial – that is 0! = 1
and n! = (n - 1)! × n
. We can use the first one to create the base case of the recursive function, because in that case we know the result already.
function factorial(n) {
if (n === 0) {
return 1;
}
}
The second thing to know about how to calculate a factorial, n! = (n - 1)! × n
, can be the recursive case.
function factorial(n) {
if (n === 0) {
return 1;
} else {
return factorial(n-1) * n;
}
}
How to calculate a factorial with a JavaScript while
loop
We said before that 0! = 1
. So, to calculate the factorial of a number with a loop, we can initialize a variable to 1
, and multiply the numbers from n
to 1
by the variable inside the loop.
In this way, if the input is higher than 1, the output will easily be 1.
function factorial(n) {
let result = 1;
for (n > 1) {
result *= n;
n--;
}
return result;
}
Conclusion
The factorial is a pretty important operator to know if you are interested in statistics and probabilities.
In this article you have learned a how to calculate a factorial, a simple application, and you have seen how to calculate it using JavaScript.
Have fun with it!
Learn to code for free. freeCodeCamp’s open source curriculum has helped more than 40,000 people get jobs as developers. Get started
Как найти факториал натурального числа по формуле — примеры решения задач
Определение факториала
Факториал — это математическая функция, которая применяется к положительным целым числам, равная произведению всех натуральных чисел от единицы до вычисляемого числа.
Факториал обозначается «n!».
Для представления факториала, приведем простой его пример: (5!;=;1cdot2cdot3cdot4cdot5;=;120.)
Осторожно! Если преподаватель обнаружит плагиат в работе, не избежать крупных проблем (вплоть до отчисления). Если нет возможности написать самому, закажите тут.
Для нахождения факториала необходимо просто по очереди перемножить все положительные натуральные числа от единицы до вычисляемого числа включительно.
Факториал математически выглядит следующим образом:
(n!;=;1cdot2cdot3cdot…cdot n;=;prod_{k=1}^nk.)
Факториал применяется в различных разделах математики, но активно он используется, когда речь заходит о комбинациях, перестановках, теории чисел, комбинаторике, математическом анализе и так далее.
В комбинаторике факториал числа n обозначает количество перестановок множества из n элементов.
Формула факториала
Из определения факториала следует формула:
Важно 3
((n;-;1)!;=;frac{n!}n.)
Расшифровав формулу, можно сделать вывод, что если мы знаем факториал числа, то можно найти факториал предыдущего числа путем деления значения факториала на само число.
Также из формулы следует, что при n=1 факториал 0!=1.
Примеры задач с решениями
Задача 1
В комнате стоит стол, вокруг которого стоят четыре стула. В комнату заходят четыре человека. Вычислите количество вариантов для рассаживания четырех человек вокруг стола.
Решение: так как количество стульев и людей совпадают, мы можем вычислить количество вариантов с помощью факториала.
(n;=;4,\4!;=;1cdot2cdot3cdot4;=;24)
Ответ: всего 24 варианта рассаживания четырех человек.
Задача 2
Вычислите (frac{3!-2!}4.)
Решение:
(frac{2!cdot(3-1)}4=frac{2!cdot2}4=frac44=1.)
Ответ: 1.
Задача 3
В расписании 11 класса на понедельник должно быть 5 предметов: алгебра, русский язык, литература, физика и геометрия. Сколько существует способов для составления расписания на этот день?
Решение:
(n;=;5,\5!;=;1cdot2cdot3cdot4cdot5;=;120.)
Ответ: 120 способов.
Задача 4
Сколько существует способов для составления указанного выше расписания из тех же 5 предметов, если требуется, чтобы урок геометрии был последним?
Решение:
(n;=;4,\4!;=;1cdot2cdot3cdot4;=;24.)
Ответ: 24 способа.
Задача 5
Сколько существует способов для составления расписания из указанных выше 5 предметов, в котором алгебра и русский язык стояли бы рядом?
Решение:
(n;=;4,\4!cdot2=;(1cdot2cdot3cdot4)cdot2;=;48.)
Ответ: 48 способов.
Задача 6
Вычислите (frac{5!-3!}{3!}.)
Решение:
(frac{3!cdot(4cdot5-1)}{3!}frac{6cdot19}6=frac{114}6=19.)
Ответ: 19.
Задача 7
Вычислите (С_4^2.)
Решение:
(С_n^m;=;frac{n!}{m!cdot(n-m)!})
(C_4^2;=;frac{4!}{2!cdot(4-2)!}=frac{4!}{2!cdot2!}=frac{4!}{2!cdot2!}=frac{2!cdot3cdot4}{2!cdot2!}=frac{12}2=6.)
Ответ: 6.
Задания для самостоятельной работы
Задача 8
Вычислите (frac{8!-6!}{55}.)
Задача 9
Вычислите (frac{121!-120!}{120!}).
Задача 10
Вычислите (С_5^3.)
Задача 11
Вычислите (С_{12}^{11})
Задача 12
Шесть друзей приобрели билеты в кино на 1-е, 2-е, 3-е места в третьем ряду, и на 1-е, 2-е, 3-е места в четвертом ряду. Сколько существует способов рассадки друзей на эти шесть мест в кинотеатре?
Задача 13
Сколько существует способов выбрать четырех дежурных из класса, в котором 20 человек?
Подсказка: используйте формулу (С_n^m;=;frac{n!}{m!cdot(n-m)!}.)
Задача 14
Вычислите 4!-3!.