#include <iostream>
#include <tchar.h>
class CFactorialCalculator
{
public:
CFactorialCalculator()
: iIncBufferSize(1024)
{
ret1 = ret2 = NULL;
iBufferSize = 0;
}
~CFactorialCalculator()
{
delete[] ret1;
delete[] ret2;
}
bool Calc(int n)
{
if(n < 0)
return false;
if(!ret1 || !ret2)
{
delete[] ret1; delete[] ret2;
AllocResult();
}
else
{
memset(ret1, 0, iBufferSize);
memset(ret2, 0, iBufferSize);
}
*ret1 = *ret2
= top = 1;
while(true)
{
if(n <= 1) break;
if(!AppendMulti(n--)) return false;
}
return true;
}
inline int GetResultCount() { return top; }
inline char* GetResult() { return ret1; }
// Helper
static void PrintToConsole(
int n, int iResultCount, char* szFactorialResult)
{
printf("%d!=", n);
for(int i = iResultCount - 1; i >= 0; i--)
{
printf("%d", szFactorialResult[i]);
}
printf("\n");
}
protected:
bool AllocResult()
{
int iNewSize = iBufferSize + iIncBufferSize;
char* r1 = new char[iNewSize];
char* r2 = new char[iNewSize];
if(!r1 || !r2)
{
delete[] r1; delete[] r1;
return false;
}
memset(r1, 0, iNewSize);
memset(r2, 0, iNewSize);
if(ret1)
{
memcpy(r1, ret1, iBufferSize);
delete[] ret1;
}
if(ret2)
{
memcpy(r2, ret2, iBufferSize);
delete[] ret2;
}
iBufferSize = iNewSize;
ret1 = r1;
ret2 = r2;
return true;
}
bool AppendMulti(int n)
{
int i, j = 0;
int m;
char* ret;
memset(ret2, 0, top);
while(n > 0)
{
m = n % 10;
for(i = 0; i < top; i++)
{
if(i + j + 1 >= iBufferSize)
{
if(!AllocResult()) return false;
}
ret2[i + j] += m * ret1[i];
if(ret2[i + j] >= 10)
{
ret2[i + j + 1] += ret2[i + j] / 10;
ret2[i + j] %= 10;
}
}
n /= 10;
j++;
}
top = (ret2[i + j - 1] ? 1 : 0) + i + j - 1;
ret = ret1; ret1 = ret2; ret2 = ret;
return true;
}
private:
char* ret1;
char* ret2;
const int iIncBufferSize;
int iBufferSize;
int top;
};
int _tmain(int argc, _TCHAR* argv[])
{
CFactorialCalculator fc;
int test[] = {
-1, 0, 1, 4, 10, 11, 100, 459, 750, 1000, 1001
};
for(int i = 0; i < sizeof(test) / sizeof(int); i++)
{
if(fc.Calc(test[i]))
{
CFactorialCalculator::PrintToConsole(
test[i], fc.GetResultCount(),
fc.GetResult()
);
}
else
{
printf("%d!=ERROR\n", test[i]);
}
}
return 0;
}