Кто-нибудь может объяснить этот алгоритм расчета больших факториалов?
Я наткнулся на следующую программу для вычисления больших факториалов (чисел до 100). Может кто-нибудь объяснить мне основную идею, используемую в этом алгоритме? Мне нужно знать только математику, применяемую при расчете факториала.
#include <cmath>
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
unsigned int d;
unsigned char *a;
unsigned int j, n, q, z, t;
int i,arr[101],f;
double p;
cin>>n;
p = 0.0;
for(j = 2; j <= n; j++)
p += log10(j);
d = (int)p + 1;
a = new unsigned char[d];
for (i = 1; i < d; i++)
a[i] = 0; //initialize
a[0] = 1;
p = 0.0;
for (j = 2; j <= n; j++)
{
q = 0;
p += log10(j);
z = (int)p + 1;
for (i = 0; i <= z/*NUMDIGITS*/; i++)
{
t = (a[i] * j) + q;
q = (t / 10);
a[i] = (char)(t % 10);
}
}
for( i = d -1; i >= 0; i--)
cout << (int)a[i];
cout<<"\n";
delete []a;
return 0;
}
1 ответ
Обратите внимание, что
n! = 2 * 3 * ... * n
чтобы
log(n!) = log(2 * 3 * ... * n) = log(2) + log(3) + ... + log(n)
Это важно, потому что если k
является положительным целым числом, то потолок log(k)
количество цифр в представлении base-10 k
, Таким образом, эти строки кода рассчитывают количество цифр в n!
,
p = 0.0;
for(j = 2; j <= n; j++)
p += log10(j);
d = (int)p + 1;
Затем эти строки кода выделяют место для хранения цифр n!
:
a = new unsigned char[d];
for (i = 1; i < d; i++)
a[i] = 0; //initialize
Тогда мы просто делаем алгоритм умножения начальной школы
p = 0.0;
for (j = 2; j <= n; j++) {
q = 0;
p += log10(j);
z = (int)p + 1;
for (i = 0; i <= z/*NUMDIGITS*/; i++) {
t = (a[i] * j) + q;
q = (t / 10);
a[i] = (char)(t % 10);
}
}
Внешний цикл работает от j
от 2
в n
потому что на каждом шаге мы будем умножать текущий результат, представленный цифрами в a
от j
, Внутренний цикл - это алгоритм умножения начальной школы, в котором мы умножаем каждую цифру на j
и нести результат в q
если необходимо.
p = 0.0
перед вложенным циклом и p += log10(j)
внутри цикла просто следите за количеством цифр в ответе.
Между прочим, я думаю, что в этой части программы есть ошибка. Состояние цикла должно быть i < z
не i <= z
в противном случае мы будем писать после конца a
когда z == d
что произойдет наверняка, когда j == n
, Таким образом заменить
for (i = 0; i <= z/*NUMDIGITS*/; i++)
от
for (i = 0; i < z/*NUMDIGITS*/; i++)
Тогда мы просто распечатаем цифры
for( i = d -1; i >= 0; i--)
cout << (int)a[i];
cout<<"\n";
и освободить выделенную память
delete []a;