c语言程序 大数阶乘同时统计结果中有多少个0
题目:
输入一个自然数n,求!n,同时统计结果中有多少个0。
1、问题分析与方案设计。
1、输入问题。题目要求输入自然数n。所以定义input()函数,使输入的为自然数,如果是字母或者其他字符则会报错提示重新输入。具体方法:先采用字符串输入,限定每一个输入的字符都在0~9之间,保证输入的是数字,避免输入的是字母或者其他字符,然后再对字符串使用atoi函数,该函数为c语言自带的函数,其功能为:把字符串转换成整型数。
2.阶乘的解决方案。两种求阶乘的基本方案:
①/*--- 利用阶乘的定义求解阶乘 ---*/
#include
void main()
{ int i,n;
long f=1;
scanf("%d",&n);
for(i=1;i<=n;i++)
f=f*i;
printf("%d!=%ld",n,f);
getch();
}
②*--- 2 递归方法求阶乘 --- */
#include "stdio.h"
long fact(int n)
{ long s;
if(n<=1)
s=1;
else
s=n*fact(n-1);
return s;
}
void main()
{int num;
scanf("%d",&num);
printf("%d!=%ld\n",num,fact(num));
getch();
但是由于这两种方案的运算结果储存在int型中,最多只能算到12!,而13!则由于结果超过范围而得出错误的值。
所以本程序采用了另外的思路来求大数的阶乘。将结果按每一位存储到数组中,所以定义了很长的数组来存储结果。经测试可以算到上万的阶乘。并对数组中的每一位进行判断,若为0则,统计一个0,最终输出结果中0的个数。
对于阶乘模块的流程图如下:
2、编程实现。 1、/**********计算阶乘,统计zero*********/
void count()
i fac[j]=m%10 temp=m/10 j<=flag 是否有进位,且j 已经到最大标记处 flag+1 统计0的个数 输出结果 结束 i+1 j+1 否 否是 否 否 是 是 { int i,j,m,flag=0,zero=0;//flag标记数据结果在数组中的最大能存储到的位置 int fac[257999]={0},temp=0;//fac储存结果,temp为进位fac[0]=1; j=0; for(i=2;i<=n;i++) { for(j=0;j<=flag;j++) { m=fac[j]*i+temp; fac[j]=m%10; temp=m/10; if(temp!=0&&j==flag) flag+=1;//当有进位,且j已经到最大标记处,则往后移一个flag } } printf("\n%d!=",n); for(j=flag;j>=0;j--)//倒着读出 { printf("%d",fac[j]); if(fac[j]==0) zero++; } printf("\n共有%d个0",zero); } 2、//菜单选择 int choice() { int c; printf("请选择:\t1.输入阶乘数n\t0.退出\n>>"); scanf("%d",&c); while(c!=0&&c!=1) { printf("输入错误, 请重新选择1或者0\n>>"); scanf("%d",&c); } return c; } 3、测试数据、测试结果、结果分析。 测试1: 测试数据:n=10 测试结果: 结果分析:输入小数10,10!结果正确,统计0的个数正确。并且能返回菜单,实现再次输入 测试2: 测试数据:选择1。输入的n为5000,显示5000!=4228577.......... 测试结果: 结果分析:本次输入的n为5000,统计0的个数为2782。如果输入10000 、20000也是可以的,但是系统运算时间较长。 源代码: #include #include #include #include int n;//全局的n 输入的数 /**********计算阶乘,统计zero*********/ void count() { int i,j,m,flag=0,zero=0;//flag标记数据结果在数组中的最大能存储到的位置 int fac[257999]={0},temp=0;//fac储存结果,temp为进位fac[0]=1; j=0; for(i=2;i<=n;i++) { for(j=0;j<=flag;j++) { m=fac[j]*i+temp; fac[j]=m%10; temp=m/10; if(temp!=0&&j==flag) flag+=1;//当有进位,且j已经到最大标记处,则往后移一个flag } } printf("\n%d!=",n); for(j=flag;j>=0;j--)//倒着读出 { printf("%d",fac[j]); if(fac[j]==0) zero++; } printf("\n共有%d个0",zero); } /*******输入n*******/ void input() { int flag; char t[100]; do{ flag=0; printf("请输入 n:\n>>"); fflush(stdin); re: gets(t);//(全部输完n再作判断) for(int i=0;(size_t)i { if(t[i]<'0' ||t[i]>'9') flag=1; } if(flag) { printf("输入有误,请重新输入:\n>>"); flag=0; //(这一步要重置flag为0,当做无误的再作判断) goto re; } }while(flag); n=atoi(t); } /**********运行界面*********/ void menu() { printf("\t\t \n\n\n\n\n"); printf("\t\t -------------------------------------\n"); printf("\t\t welcome to \n"); printf("\t\t n! calculate \n"); printf("\t\t -------------------------------------\n"); } //菜单选择 int choice() { int c; printf("请选择:\t1.输入阶乘数n\t0.退出\n>>"); scanf("%d",&c); while(c!=0&&c!=1) { printf("输入错误, 请重新选择1或者0\n>>"); scanf("%d",&c); } return c; } //主函数 void main() { while(1) { menu(); switch(choice()) { case 1: input(); //输入n count(); //计算n! break; case 0: cout<<"\n谢谢使用再见!\n"; exit(0); //程序正常退出 } } } 阶乘的计算及处理程序设计 一、问题描述 要求输入一个自然数n,求n!,同时统计结果中有几个0。 二、课题分析 1)计算n!。 2)统计0的个数。 三、数据结构的设计 x:输入的数n i:n! b:储存数据i上的各位上的数,从而判断b是否为0 j:统计0的个数 四、处理结构的设计 建立两个函数f1和f2,使f1函数起到求阶乘的作用,f2函数起到求0个数的作用。 求阶乘流程图 计算0的个数流程 五、源程序 1)主要结构体: f1函数: long int f1(int x) { long int i; //声明长整型变量i if (x==0||x==1) //采用递归函数f1求阶乘i=1; else i=f1(x-1)*x; return (i); } f2函数: int f2(int i) {int j=0; int b=0; while(i>=10) //循环结构,判断末位是否为零,再去末位{b=i %10; if(b==0)j++; i=i/10; } return (j); } 2)整体: #include //阶乘各算法的 C++ 类实现 #include long fact(int n) 1 { 2 long k; 3 if (n<0) 4 { 5 printf( “Data error!\n”); 6 exit(0); 7 } 8 else if (n==0||n==1) k=1; 9 else k=n*fact(n-1); 10 return k; 11 } main() { int n; long f; printf(“Please input an integral number:\n”); scanf(“%d”, &n); f=fact(n); printf(“%d!=%ld\n”, n, f); } 求fact(4)的详解过程, 执行了的语句用红色表示long fact(4) 1 { 2 long k; 3 if (4<0) 4 { 5 printf( “Data error!\n”); 6 exit(0); 7 } 8 else if (4==0||4==1) k=1; 9 else k=4*fact(4-1); /*断点1:调用fact(3)*/ 10 return k; 11 } long fact(3) 1 { 2 long k; 3 if (3<0) 4 { 5 printf( “Data error!\n”); 6 exit(0); 7 } 8 else if (3==0||3==1) k=1; 9 else k=3*fact(3-1); /*断点2:调用fact(2)*/ 10 return k; 11 } long fact(2) 1 { 2 long k; 3 if (2<0) 4 { 5 printf( “Data error!\n”); 6 exit(0); 7 } 8 else if (2==0||2==1) k=1; 9 else k=2*fact(2-1); /*断点3:调用fact(1)*/ 10 return k; 11 } 北华航天工业学院 课程设计报告(论文) 设计课题:计算N的阶乘 专业班级: 学生姓名: 指导教师: 设计时间:2010年12月16日 北华航天工业学院电子工程系 微机原理与接口技术课程设计任务书 指导教师:刘金梅教研室主任: 2010年12 月18 日 内容摘要 本次课程设计编写计算N!的程序。数值N由键盘输入,结果在屏幕上输出,通过编制一个阶乘计算程序,了解怎样在汇编语言一级上实现高级语言中的数学函数。其难点在于随着N的增大,其结果远非寄存器所能容纳。这就必须把结果放在一个内存缓冲区中。然而乘法运算只限于两个字相乘,因此要确定好算法,依次从缓冲区中取数,进行两字相乘,并将DX中的高16位积作为产生的进位。 索引关键词:N的阶乘汇编语言内存缓冲区 目录 序言————————————————————5 正文————————————————————5 一、程序算法————————————————-—-5 二、源程序—————————————————-—-6 三、程序运行与调试—————————————-—11 四、N的阶乘程序流动图——————————-—-—11 心得体会——————————————————13 参考文献——————————————————13 序言 本文是关于微型计算机原理写文件课程设计。编写程序,将内存区域中用调试程序(DEBUG)设置好的一连串数据(以Ctrl+z为结束符)做为一个文件存入磁盘,文件名为DATA.ASM。内存区域的段地址和偏移地址在程序中输入。 随着计算机的高速发展,微型计算机已经应用到各个领域,微型计算机原理应用技术已经成为电子信息的核心产业。 微型计算机原理是计算机科学与技术、通讯工程、电气工程、机电工程的核心课程。 通过这次课程设计,是我们更好地理解了课程中所学的理论知识,并把实际问题转化为理论知识,学会如何把学到的知识用于解决实际问题,培养我们的动手能力。 正文 一、程序算法 阶乘的定义为N!=N(N-1)(N-2)……2,从左至右依次计算,结果保存在缓冲区BUF中。缓冲区BUF按结果由高到低依次排列。程序首先将BP初始化为N,N 不等于0或1则将N送入BUF缓冲区最低字节单元中。然后使BP为N-1,以后BP依次减1,直到变化为1为止。每次让BP与BUF中的字节单元按由低到高的次序相乘。低位结果AX仍保存在相应的BUF字节单元中,高位结果DX则送到进位字单元CY中,作为高字相乘时从低字来的进位,初始化CY为0.计算结果的长度随着乘积运算而不断增长。由字单元LEN指示。LEN单元初始化为1。当最高字单元与BP相乘时。若DX不为0,则结果长度要扩展。 微机原理 课程设计说明书设计题目:大数阶乘与排序 专业 班级 学生 指导教师 2014 年春季学期 目录 目录 (1) 一.课设目的与要求 (2) 1.课设目的 (2) 2.题目要求 (2) 二.基本原理 (2) 1.大数阶乘原理设计 (2) 2.排序原理设计 (2) 三.架构设计 (2) 四.方案实现与测试 (3) 五.分析总结 (9) 六.参考文献 (9) 一.课设目的与要求 1.课设目的:检验和提高学生在汇编语言程序设计,微机原理与接口应用方面分析问 题与解决问题的能力 2.题目要求: 1).要求实现用汇编语言编写设计一个求解大数的阶乘精确值的程序;采用字节型数组 存放阶乘结果的每个数字位,采用逐位相乘,再对每一位规格化来实现;输出结成结果的位数及尾零的个数。 2).用汇编语言编写设计快速排序与希尔排序程序,注意合理使用堆栈,以避免堆栈溢 出,进一步动态显示排序过程。 二.基本原理 1.大数阶乘原理设计:我们在处理一个大于一定范围的数的阶乘时,无论使用什么类型去保存运算结果都必然会发生溢出,这势必会导致运算结果出错。使用数组来模拟数字,这样无论结果数字有多大,只要数组的长度够长就能表示出来,用这个办法可以进行大数据的运算。 2.排序原理设计:快速排序原理:首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。 三.架构设计 核心思想就是把计算结果每一位上的数字保存到一个数组成员中,例如: 把112保存至数组中,保存结果应该是 result[0] 2 result[1] 1 result[2] 1 把整个数组看成一个数字,这个数字和一个数相乘的时候,需要每一位都和这个乘数进行相乘运算还需要把前一为的进位加上。运算方法和小学数学是一样的,乘积的个位是当前位上应该表示的数字,10位以上的需要进位。因为乘数不可能大于10000,所以乘数和一个小于10的书相乘的时候不会大于100000,再加上前一位的进位用一个int型数据来保持这个结果就没有问题。写法如下: int 结果= result[x] * 乘数+ 进位; 每一位的计算结果有了,把这个结果的个位数拿出来放到这个数组元素上: result[x] = 结果%10; 接下来的工作就是计算出进位: 进位= 结果/ 10; 这样一位一位的把整个数组计算一遍,最后可能还有进位,用同样的方法,把进位的数值拆成单个数字,放到相应的数组元素中。 大数的阶乘 众所周知,阶乘的定义就是n! = (n-1)!*n,但是有基本的初始条件的,即0! = 1 因此1! = 1*0! = 1 * 1 = 1; 2! = 2*1! = 2 * 1 = 2; 依次类推,但是当n足够大时,整型根本无法装下n的阶乘,如果用C语言来实现的话,根本不可能,那怎么办呢? 其实阶乘也无非是乘法和加法罢了,如4!= 24;我们可以用数组来存各位,结舌数组的起始长度是1哈,每当遇到超过长度时,就自加1,不过这里要稍微处理下的,我们可以倒过来存,以便做乘法的,可以这样来存。 4! 4 2 5! = 5 * 4!,可以用5去乘以4,如果大于10则需向高位进位,下一位的结果就等于下一位乘以5然后加上刚才的进位,当然也要取余数哈,然后继续看有没进位哈,知道遍乘数组每一位哈。 给个能求1000!的例子,用C语言实现的,供大家参考,以便交流学习哈。 #include 实验五 一、实验内容 1、掌握3种循环结构:while,do-while,for的区别与联系,以及他们之间相互转换的方法,并能正确使用他们. 2,掌握与循环语句相关的break语句和continue语句的使用方法. 二、实验目的 1、掌握3种循环结构:while,do-while,for的区别与联系,以及他们之间相互转换的方法,并能正确使用他们. 2,掌握与循环语句相关的break语句和continue语句的使用方法. 三、实验步骤 实践教程例题1 1.输入正整数n,计算n的阶乘. 2.实践教程例2 输入若干字符,统计其中数字字符.白字符和其它字符的个数,输入EOF结束. 3、实践教程例3 N个人围坐成一圈,从1开始顺序编号;游戏开始,从第一个人开始由1到m循环报数,报到m的人退出圈外,问最后留下的那个人原来的序号。 4`书2.3 设计程序将输入的百分制成绩转换为五分制输出,90分以上为5分,80~89为4分,70~79为3分,60~69为两分,60分以下为1分。 书2.5 编译打印如下图形 * * * * * * * * * * * * * * * * * * * * * * * * *阶乘的计算和处理程序设计
阶乘运算
N阶乘的递归调用展开式
计算N的阶乘
大数阶乘与快速排序算法(汇编)
大数的阶乘
输入正整数n,计算n的阶乘c++实验报告