大数运算也是刚刚接触 ,因此找了资料和代码熟悉下。从搜索情况来看,阶乘被人提及比较多。因此我也在搜到文章中 选了一个代码,进行了注释。
代码不难,是一位博主写的。但是代码没有注释,我为了方便以后自己观看 和 与大家交流 贴出来分享下 。可能有些地方不是很对,欢迎指正,杜绝恶意评价。
下期预告:十六进制转成十进制,特别之处在于可以输入任意长度的十六制,也属大数运算。
网上有类似的,但希望自己能有一个学习过程的记录。 希望自己能坚持更新下来。贵在坚持
#include "stdint.h"
#include "string.h"
#include "stdio.h"
//定义short int 为 s_int 16位
#define s_int short int
//定义最大的位数(指结果值)
#define MAXDIGIT 50000
//定义权 也就是基数为10
#define RADIX 10
//定义一个函数实现进位
//返回值为bool 表明正确与否
bool carry(s_int result[],int &dgts){
int i;
s_int carry_value = 0;
//这里将上次计算得到的结果值(未进位) 并告知当前结果值占的位数
//比如上次 3! * 4后=24 但是是存储在result[0]中的 digits=0
//当然下面的肯定不会执行(因为digits=0) 不要急 因为它的
//下面一个就是处理他的问题
for(i=0;i<dgts;i++)
{
result[i] +=carry_value ;//从最低位开始计算 初始进位值为0
//判断该位是否需要进位 然后计算进位值
//比如12 那么进位为1(添加到result[1]上) 余数为2(存储在result[0])
carry_value =(result[i]< RADIX)?0:(result[i]/RADIX);
result[i] -= carry_value * RADIX; //进位后以后得到的该位置值
}
//处理最后一位
//若需要进位,则循环进位,直到需要进位为止
//注意 这里i是+1后的
result[i] += carry_value;
while(result[i]>=RADIX && i<MAXDIGIT)
{
carry_value = result[i] / RADIX;
result[i] -= carry_value * RADIX;
result[++i] = carry_value;
++dgts;
}
if(i >= MAXDIGIT)
return false;
return true;
}
//定义一个阶乘函数 factorial
//返回值是一个int类型 其实就是标志 出错就返回-1
//传入n 即 你要求的那个数的阶乘n! result 指代结果值
int factorial(int n ,s_int result[]) {
int digits = 0; //位数记录 初始设为0
result[0] = 1 ; //结果初始为1
//0!=1
if(n==0) return 1;//返回1只是表明计算正确 结果值其实在上面的初始化result[0]=1
//开始计算n! 这里我们从2开始 是因为1没有必要
//比如求4! 那么就是1 * 2 * 3 *4 所以这里用n+1
for(int i=2;i<n+1;i++){
//以下都是前一次result[] 乘以i值
for(int j=0;j<=digits;++j)
{
//关键一步 如果一个数用数组来存储
/*
举例: 5!
先看4!
4! = 3!* 4 = 2! * 3 * 4
2! = 2*1 省略1 就是i从2开始
得到的结果值存在result[]数组中 result每一个元素都能存0-9的数
比如3!= 6那么存到result[0]中 4!= 24 那么只存到result[0]就不够了
因为result[0]只能存0-9 但是结果是24 所以我们要把多余的放到result[1]中
相当于进位了2 result[0] 只剩下4了 而result[1]原来是0 现在+2
result[1] = 2;
ok 现在来看5! =4!* 5 =24 * 5
24 不能用整体来看 而是分别存储在result[1] reuslt[0]中 2 4 来看
那么*5 是最低位开始乘 也就是 4*5 即下文result[0] * 5 然后是
result[1]* 5 先不进位 只是存储在各自的result[i]位中
注意: result[]要计算多少位 是根据digits 位数来进行的 比如一开始
digits = 0 是因为结果值只占一位 存储在result[0] 后来4!=24 那么就要
存储到result[1] 和result[0] digits=1
*/
result[j] *= i;
}
//上面已经把 计算结果值 写入到各自的位中 下面要判断进位 也就是 每乘以一个数就要判断进位一次
//比如 9!=8!*9 =7!*8*9=...=1!*2 *3*...*9 每次都是上一次结果 * 数n(从2,3,4,5...9为止)
if(!carry(result,digits))
break;
}
}
//定义一个打印函数
void print(s_int result[],const int &digits){
int i;
if(digits <10)
{
for(int i = digits;i>=0;i--)
{
printf("%d",result[i]);
}
}else{
printf("%d.",result[digits]);
for(i=digits-1;i>0;i--)
{
printf("%d",result[i]);
}
printf("E %d",digits);
}
}
//主程序入口
int main(void)
{
s_int result[MAXDIGIT];
int n;
int digits;
//提示信息
printf("Please input the number that you want to calulate the n!\n");
//用户输入n 求n!
scanf("%d",&n);
//判断n值 限制条件可以自己设定
if(n < 0) {
printf("Error:A positive integer is needed!");
return 0;
}
//主要算法和函数 函数包括:计算n! 和 打印结果值
if((digits = factorial(n,result))== -1){
printf("over flow");
return 0;
}else
{
print(result,digits);
return 0;
}
}