无论是 int 还是 long long 还是 unsigned long long 型都无法计算到50的阶乘
int 四个字节 32位 范围:-2^31——2^31 -1 10^9次方数量级
unsigned long long 8个字节 64位 范围0——2^64 -1 10^19次方数量级
显然 50的阶乘 远超 上述数量级
所以这里常规方法 不在适用 引入 高精度算法 概念 适用 +-*/
其基本方法就是就是引入数组
比如上述50的阶乘 常规方法没法存下它 但是 int arr[1000] 这个数字肯定可以存下它 50!的每一位存在一个数组元素里面 这样就解决了 大数的乘法
但是值得注意的是 对于50!(30414093201713378043612608166064768844377641568960512000000000000)这个数的话我们往 整型数组 里面放 比较繁琐 需要一个一个的放。
这里引入如下代码:
char arr1[1000]="304140932017133780436126081660647688440512000000000000";
int arr2[1000]={0};
int sz=strlen(arr1); //求字符串长度
for(int i=0;i<sz;++i)
{
arr2[i]=arr1[sz-1-i]-'0'; //字符串在内存中存的是 ASC|| 码 这里减‘0’; 就把它还原成本来的数字
}
由上述代码 即可实现大数的写入
这里解释为什么逆序给他存入arr2的 因为我们做算数都是从各位开始的 ,所以逆序存入,方便向高进位!!!
对于本题 用不到上述方法 因为这里是从 1往上乘的 不用存入大数
代码如下:
//最终优化版本
#include<stdio.h>
#include<string.h>
//高精度算法
int arr2[100] = { 0 };
int main()
{
int n = 0;
int a = 0;
scanf("%d", &n);
int i = 1;
int arr2[1000] = {1};//存放阶乘
int arr4[1000] = { 0 };
for (i = 1; i <= n; ++i)
{
阶乘
int flag = 0; //进位标志
int j = 1;
for(j=0;j<1000;++j)
{
arr2[j] = (arr2[j] * i) + flag;
flag = arr2[j] / 10;
arr2[j] = arr2[j] % 10;
}
求和
flag = 0; //进位标志
j = 1;
for(j=0;j<1000;++j)
{
arr4[j] = arr4[j] + arr2[j] + flag;
flag = arr4[j] / 10;
arr4[j] = arr4[j] % 10;
}
}
for (int j = 999; j >= 0; --j)
{
if (arr4[j] != 0)
{
a = j;
break;
}
}
for(i=a;i>=0;--i)
printf("%d", arr4[i]);
return 0;
}
对于阶乘部分解释:数字的低位在低地址 高位在高地址
代码比较好理解 不多坠入
+ - / 同理
记住高精度的算法的精髓 :利用数组 来存放结果!!!!
数字的低位在低地址 高位在高地址
一方面:方便向高位进位
另一方面就是:做加减法 位权相同的要对齐 都从数组arr[0]开始 自然就对齐了