C/C++语言中,int范围为[-231, 231-1] 即 [-2147483648, 2147483647]。
在进行阶乘运算中,12!!!=479001600,13!!!=6227020800,也就意味着超过13的阶乘就不能用int型进行存储。对于大数的阶乘,要换一种方式进行存储。
输入一个数值n,首先要估算n!的位数:
int getSize(int n) //计算结果的大概位数
{
int i, j, num;
for(i = 1, j = n; j / 10 > 0 || j % 10 > 0; ++i)
{
j /= 10;
}
//num=n*--i+1; //此计算式为多次总结归纳得到
num = n*--i / 3 + 1; //一个int存储的数字的范围为0~9999,按理说是n*--i/4+1,此处多申请一些以防开辟的空间不足
return num;
}
通过此函数得到的位数会比实际的位数要多。
得到位数size之后,申请一个长度为size的int型数组,初始化末位为1,其余全为0;
然后从末位起倒着乘以每一个数,将数组中每一个数字的范围为0~9999,超过范围的数字向前进位。最后将结果通过string字符串返回。代码如下:
string factorial(int n)
{
string outp;
int *temparr, num;
int getSize(int n);
int getNumLength(int n);
int i, j, k;
int wsize = 10000;
int size = getNumLength(wsize) - 1;
num = getSize(n);
temparr = new int [num];
for(i = 0; i < num; ++i)
{
if(i == num - 1) temparr[i] = 1;
else temparr[i] = 0;
}
if(n == 0) temparr[num - 1] = 1;
else
{
for(i = 1; i <= n; ++i)
{
int count = num - getSize(i) - 1;
for(j = num - 1; j >= count && j - 1 >= count; --j)
temparr[j] *= i;
for(k = num - 1; k >= count && k - 1 >= count; --k)
{
if(temparr[k] > wsize)
{
temparr[k - 1] += (temparr[k] / wsize);
temparr[k] = (temparr[k] % wsize);
}
else continue;
}
}
}
int midd = 0;
for(i = 0; i < num; ++i)
{
if(temparr[i] == 0) midd += 1;
else break;
}
char s[8];
sprintf(s, "%d", temparr[midd]); //从第midd位开始为非0数
outp += s;
for(i = midd + 1; i < num; ++i)
{
sprintf(s, "%04d", temparr[i]); //四位有效数字,不足的情况用0填充
outp += s;
}
if(temparr)
{
delete [] temparr;
temparr=NULL;
}
return outp;
}
其中,int getNumLength(int n)函数的实现代码为:
int getNumLength(int n)
{
if(n == 0) return 1;
else if(n < 0) return -1;
int size = 0;
while(n)
{
n /= 10;
++size;
}
return size;
}
main函数中:
int main(int argc, char* argv[])
{
int getSize(int n);
int getNumLength(int n);
string factorial(int n);
cout << "//------------------------------大数阶乘------------------------------//" << endl;
cout << "//--------- 数组求阶乘,为方便运算,原则不大于100000,否则会很慢 --------//" << endl;
int n;
cin >> n;
string s;
double timebegin = (double)clock() / CLOCKS_PER_SEC;
if(n < 0)
{
cout << "输入有误!!!" << endl;
return 0;
}
else
{
s = factorial(n);
cout << n << "!=";
cout << s << endl;
if(n >= 30) //启用科学计数法
{
cout << n << "!=" << s[0] << ".";
for(int i = 1; i < 20; ++i)
cout << s[i];
cout << "e+" << s.size() - 1 << endl;
}
}
printf("time: %.6f\n\n", (double)clock() / CLOCKS_PER_SEC - timebegin);
system("pause");
return 0;
}
运行结果:
输入 | 结果 |
---|---|
20!20!20! | ![]() |
1000!1000!1000! | ![]() |
20000!20000!20000! | ![]() |
欢迎大家批评指正。