c语言经典问题
- 格式:doc
- 大小:29.00 KB
- 文档页数:7
文章由劍舞沖天精心整理,希望對大家的學習和工作帶來幫助整理人:劍舞沖天整理時間:2011-4-10C語言超級經典400道題目1、C語言程式的基本單位是____ A) 程式行 B) 語句 C) 函數 D) 字元、C、12、C語言程式的三種基本結構是____ A、順序結構,選擇結構,迴圈結構 B、遞歸結構,迴圈結構,轉移結構 C、嵌套結構,遞歸結構,順序結構 D、迴圈結構,轉移結構,順序結構、A、13、C語言規定,程式中各函數之間 A) 既允許直接遞歸調用也允許間接遞歸調用 B) 不允許直接遞歸調用也不允許間接遞歸調用 C) 允許直接遞歸調用不允許間接遞歸調用 D) 不允許直接遞歸調用允許間接遞歸調用、A、14、C語言中可處理的檔類型是( ) A) 文本檔和數據檔 B)文本檔和二進位檔 C) 數據檔和二進位檔 D)數據代碼檔、B、15、C語言可執行程式的開始執行點是( ) A) 程式中第一條可執行語句 B) 程式中第一個函數 C) 程式中的main函數 D) 包含檔中的第一個函數、C、16、C語言提供的合法的數據類型關鍵字是 A)double B) short C) integer D) char、B、17、C語言中,運算對象必須是整型數的運算符是 A) % B) \ C) %和\ D) * *、A、18、C語言中函數返回值的類型是由( )決定。
A) return語句中的運算式類型 B) 調用函數的主調函數類型 C) 調用函數時臨時 D) 定義函數時所指定的函數類型、D、19、C語言中數組名作為參數傳遞給函數,作為實在參數的數組名被處理為_____。
A、該數組的長度。
B、該數組的元素個數。
C、該數組中各元素的值。
D、該數組的首地址。
、D、110、C語言中數組下標的下限是________。
A、1 B、0 C、視具體情況 D、無固定下限、B、111、C語言中提供的合法關鍵字是____ A、swith B、cher C、case D、default、D、112、C語言中文件的存取方式是________。
C语言程序设计习题授课对象:信息奥赛辅导成员授课时间:题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?__________________________________________________________________ 程序分析:兔子的规律为数列1,1,2,3,5,8,13,21….___________________________________________________________________程序源代码:main(){long f1,f2;int i;f1=f2=1;for(i=1;i<=20;i++){ printf(“%12ld %12ld”,f1,f2);if(i%2==0) printf(“\n”);/*控制输出,每行四个*/f1=f1+f2;/*前两个月加起来赋值给第三个月*/f2=f1+f2;/*前两个月加起来赋值给第三个月*/}}上题还可用一维数组处理,you try!题目:判断101-200之间有多少个素数,并输出所有素数。
__________________________________________________________________ 程序分析:判断素数的方法:用一个数分别去除2到sqrt(这个数),如果能被整除,则表明此数不是素数,反之是素数。
___________________________________________________________________程序源代码:#include “math.h”main(){int m,i,k,h=0,leap=1;p rintf(“\n”);for(m=101;m<=200;m++){ k=sqrt(m+1);for(i=2;i<=k;i++)if(m%i==0){leap=0;break;}if(leap) {printf(“%-4d”,m);h++;if(h%10==0)printf(“\n”);}leap=1;}printf(“\nThe total is %d”,h);}题目:打印出所有的“水仙花数”,所谓“水仙花数”是指一个三位数,其各位数字立方和等于该数本身。
c语言常见问题集C语言作为一种古老而强大的编程语言,在使用过程中可能会遇到各种常见问题。
以下是一些C语言常见问题及解决方法的集合:1.指针问题:问题:指针使用不当导致内存泄漏或段错误。
解决方法:谨慎使用指针,确保正确的内存分配和释放,避免野指针。
2.内存泄漏:问题:未正确释放动态分配的内存。
解决方法:在不再使用内存时,使用free函数释放动态分配的内存。
3.数组越界:问题:访问数组元素时超出了数组边界。
解决方法:确保数组索引在合法范围内,使用循环时注意控制循环边界。
4.未初始化变量:问题:使用未初始化的变量。
解决方法:在使用变量之前确保对其进行初始化,避免产生未定义行为。
5.逻辑错误:问题:程序的输出与预期不符。
解决方法:仔细检查代码逻辑,使用调试工具进行单步调试,查找错误的源头。
6.编译错误:问题:编译时出现错误。
解决方法:仔细阅读编译器报错信息,检查代码语法错误,确保使用正确的语法和标准库函数。
7.字符串处理问题:问题:字符串操作时未考虑字符串结束符\0。
解决方法:确保字符串以\0结尾,使用字符串处理函数时注意边界条件。
8.文件操作问题:问题:未正确打开、关闭文件,或者在未打开文件的情况下进行文件操作。
解决方法:在使用文件之前确保正确打开,使用完毕后关闭文件,检查文件是否成功打开。
9.结构体使用问题:问题:结构体成员的访问不当。
解决方法:确保使用正确的结构体成员名,避免结构体成员越界访问。
10.数据类型不匹配:-问题:不同数据类型之间的不匹配导致错误。
-解决方法:确保进行运算或赋值时,数据类型一致或符合隐式转换规则。
以上问题及解决方法提供了一些基本的指导,但在实际编码中,关键在于谨慎、仔细和严谨,同时善用调试工具和编程工具,及时修复潜在问题。
1.寻找数组中的最大值和最小值2.寻找数组中的中位数3.查找数组中给定元素的索引4.反转数组5.合并两个升序数组6.移位数组7.查找两个数组的交集8.查找两个数组的并集9.查找两个数组的差集10.寻找数组中的众数11.寻找数组中的缺失元素12.寻找数组中的重复元素13.计算数组的和14.计算数组的平均值15.计算数组的方差16.计算数组的标准差17.比较两个数组是否相等18.复制数组19.排序数组20.搜索数组(线性搜索)21.搜索数组(二分搜索)22.插入元素到数组23.删除元素到数组24.更新数组中的元素25.创建动态数组26.释放动态数组27.字符串复制28.字符串连接29.字符串比较30.字符串搜索31.字符串替换32.字符串分割33.字符串反转34.字符串大小写转换35.字符串修剪36.计算字符串长度37.字符串格式化38.链表创建39.链表插入40.链表删除41.链表搜索42.链表反转43.链表排序44.链表合并45.链表复制46.链表释放47.树创建48.树插入49.树删除50.树搜索51.树反转52.树排序53.树合并54.树复制55.树释放56.堆创建57.堆插入58.堆删除59.堆搜索60.堆反转61.堆排序62.堆合并63.堆复制64.堆释放65.图创建66.图插入67.图删除68.图搜索69.图反转70.图排序71.图合并72.图复制73.图释放74.队列创建75.队列插入76.队列删除77.队列搜索78.队列反转79.队列排序80.队列合并81.队列复制82.队列释放83.栈创建84.栈插入85.栈删除86.栈搜索87.栈反转88.栈排序89.栈合并90.栈复制91.栈释放92.哈希表创建93.哈希表插入94.哈希表删除95.哈希表搜索96.哈希表反转97.哈希表排序98.哈希表合并99.哈希表复制100.哈希表释放。
C语言超级经典400道题目1、C语言程序的基本单位是____ A) 程序行 B) 语句 C) 函数 D) 字符、C、12、C语言程序的三种基本结构是____ A、顺序结构,选择结构,循环结构 B、递归结构,循环结构,转移结构 C、嵌套结构,递归结构,顺序结构 D、循环结构,转移结构,顺序结构、A、13、C语言规定,程序中各函数之间 A) 既允许直接递归调用也允许间接递归调用 B) 不允许直接递归调用也不允许间接递归调用 C) 允许直接递归调用不允许间接递归调用 D) 不允许直接递归调用允许间接递归调用、A、14、C语言中可处理的文件类型是( ) A) 文本文件和数据文件 B)文本文件和二进制文件 C) 数据文件和二进制文件 D)数据代码文件、B、15、C语言可执行程序的开始执行点是( ) A) 程序中第一条可执行语句 B) 程序中第一个函数 C) 程序中的main函数 D) 包含文件中的第一个函数、C、16、C语言提供的合法的数据类型关键字是 A)double B) short C) integer D) char、B、17、C语言中,运算对象必须是整型数的运算符是 A) % B) \ C) %和\ D) * *、A、18、C语言中函数返回值的类型是由( )决定。
A) return语句中的表达式类型 B) 调用函数的主调函数类型 C) 调用函数时临时 D) 定义函数时所指定的函数类型、D、19、C语言中数组名作为参数传递给函数,作为实在参数的数组名被处理为_____。
A、该数组的长度。
B、该数组的元素个数。
C、该数组中各元素的值。
D、该数组的首地址。
、D、110、C语言中数组下标的下限是________。
A、1 B、0 C、视具体情况 D、无固定下限、B、111、C语言中提供的合法关键字是____ A、swith B、cher C、case D、default、D、112、C语言中文件的存取方式是________。
1.这样的初始化有什么问题?char *p = malloc(10); 编译器提示“非法初始式” 云云。
答:这个声明是静态或非局部变量吗?函数调用只能出现在自动变量(即局部非静态变量) 的初始式中。
因为静态变量的地址必须在编译的过程中就确定下来而malloc()申请的内存地址是在运行时确定的。
2. *p++ 自增p 还是p 所指向的变量?答:后缀++ 和-- 操作符本质上比前缀一目操作的优先级高, 因此*p++ 和*(p++) 等价, 它自增p 并返回p 自增之前所指向的值。
要自增p 指向的值, 使用(*p)++, 如果副作用的顺序无关紧要也可以使用++*p。
3 我有一个char * 型指针正巧指向一些int 型变量, 我想跳过它们。
为什么如下的代码((int*)p)++; 不行?答:在C 语言中, 类型转换意味着“把这些二进制位看作另一种类型, 并作相应的对待”; 这是一个转换操作符,根据定义它只能生成一个右值(rvalue)。
而右值既不能赋值, 也不能用++ 自增。
(如果编译器支持这样的扩展,那要么是一个错误, 要么是有意作出的非标准扩展。
) 要达到你的目的可以用:p = (char *)((int *)p + 1);或者,因为p 是char * 型, 直接用p += sizeof(int);4.空指针和未初始化的指针是一回事吗?答:空指针在概念上不同于未初始化的指针:空指针可以确保不指向任何对象或函数;而未初始化指针则可能指向任何地方。
5.我可以用0来表示空指针吗?答:根据语言定义, 在指针上下文中的常数0 会在编译时转换为空指针。
也就是说, 在初始化、赋值或比较的时候,如果一边是指针类型的值或表达式, 编译器可以确定另一边的常数0 为空指针并生成正确的空指针值。
因此下边的代码段完全合法:char *p = 0;if(p != 0)然而, 传入函数的参数不一定被当作指针环境, 因而编译器可能不能识别未加修饰的0 “表示” 指针。
经典C源程序100例题目:有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?1.程序分析:可填在百位、十位、个位的数字都是1、2、3、4。
组成所有的排列后再去掉不满足条件的排列。
2.程序源代码:main(){int i,j,k;printf("\n");for(i=1;i<5;i++) /*以下为三重循环*/for(j=1;j<5;j++)for (k=1;k<5;k++){if (i!=k&&i!=j&&j!=k) /*确保i、j、k三位互不相同*/printf("%d,%d,%d\n",i,j,k);} }==============================================================【程序2】题目:企业发放的奖金根据利润提成。
利润(I)低于或等于10万元时,奖金可提10%;利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可可提成7.5%;20万到40万之间时,高于20万元的部分,可提成5%;40万到60万之间时高于 40万元的部分,可提成3%;60万到100万之间时,高于60万元的部分,可提成1.5%,高于 100万元时,超过100万元的部分按1%提成,从键盘输入当月利润I,求应发放奖金总数?1.程序分析:请利用数轴来分界,定位。
注意定义时需把奖金定义成长整型。
2.程序源代码:main(){long int i;int bonus1,bonus2,bonus4,bonus6,bonus10,bonus;scanf("%ld",&i);bonus1=100000*0.1;bonus2=bonus1+100000*0.75;bonus4=bonus2+200000*0.5;bonus6=bonus4+200000*0.3;bonus10=bonus6+400000*0.15;if(i<=100000)bonus=i*0.1;else if(i<=200000)bonus=bonus1+(i-100000)*0.075;else if(i<=400000)bonus=bonus2+(i-200000)*0.05;else if(i<=600000)bonus=bonus4+(i-400000)*0.03;else if(i<=1000000)bonus=bonus6+(i-600000)*0.015;elsebonus=bonus10+(i-1000000)*0.01;printf("bonus=%d",bonus); }==============================================================【程序3】题目:一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少?1.程序分析:在10万以内判断,先将该数加上100后再开方,再将该数加上268后再开方,如果开方后的结果满足如下条件,即是结果。
一,闰年问题#include<stdio.h>void main(){int a;printf("please input the data of years:");scanf("%d",&a);if(a%400==0||(a%4==0&&a%100!=0))printf("\n闰年:%d",a);}二,数字整除问题#include<stdio.h>void main(){int a=1,i=0;printf("能被7整除的数:\n");while(a<=100){if(a%7==0){printf("%4d",a);i++;if(i%5==0)printf("\n");}a++;}}三,五层递加三角#include<stdio.h>void main(){int a,b,n=1;while(n<=5){a=1,b=1;while(a<=5-n){printf(" ");a++;}while(b<=2*n-1){printf("*");b++;}printf("\n");n++;}}四,水仙花数#include<stdio.h>void main(){int a,m,n,q,p=1;a=100;while(a<1000){m=a/100;n=a/10-m*10;q=a-m*100-n*10;if(a==m*m*m+n*n*n+q*q*q){printf("%5d",a);if(p%2==0)printf("\n");p++;}a++;}}五,最小公倍数#include<stdio.h>int gy(int x,int y){int r;if(x<y){r=x;x=y;y=r;}r=x%y;while(r!=0){x=y;y=r;r=x%y;}return (y);}int gb(int m,int n){int p;p=m*n/gy(m,n);return (p);}void main(){int a,b,c;printf("please enter the data you want to handle:");scanf("%d,%d",&a,&b);c=gb(a,b);printf("%d",c);}六,1+1/3+1/5.....#include<stdio.h>void main(){int n,i;float sum=0.0;scanf("%d",&n);i=1;while(i<=n){sum +=___1.0/(2*i-1);i++;}printf("%.3f",sum);}七,1+1/(1+2)+1/(1+2+3).....#include<stdio.h>void main(){int a,b,c=0;float d=0.0;a=1;scanf("%d",&b);while(a<=b){c+=a;a++;d+=1.0/c;}printf("%d\n",c);printf("%.3f",d);}八,1/(1*2*3*4....*b)#include<stdio.h>void main(){int a,b,c=1;float d;scanf("%d",&b);a=1;while(a<=b){c*=a;a++;d=1.0/c;}printf("%d\n",c);printf("%.3f\n",d);}九,从大到小排列数组,求和,取极差#include<stdio.h>void main(){int a[10],m=0,i,j,t,c;float d=0.0;while(m<10){scanf("%d",&a[m]);m++;}for(i=0;i<10;i++)printf("%3d",a[9-i]);printf("\n");for(i=0;i<10;i++)for(j=0;j<9-i;j++){if(a[j]<a[j+1]){t=a[j];a[j]=a[j+1];a[j+1]=t;}}for(i=0;i<10;i++)printf("%3d",a[i]);c=a[0]-a[9];printf("\n%d",c);for(i=0;i<10;i++)d+=a[i];printf("\n%.3f",d/10.0);}十,矩阵转置及其元素最大值#include<stdio.h>void main(){int i,j,a[2][3],b[3][2],max;for(i=0;i<2;i++)for(j=0;j<3;j++)scanf("%d",&a[i][j]);for(i=0;i<2;i++){for(j=0;j<3;j++)printf("a[%d][%d]=%d ",i,j,a[i][j]);printf("\n");}for(i=0;i<2;i++){for(j=0;j<3;j++){b[j][i]=a[i][j];}}for(i=0;i<3;i++){for(j=0;j<2;j++)printf("b[%d][%d]=%2d ",i,j,b[i][j]);printf("\n");}max=a[0][0];for(i=0;i<2;i++)for(j=0;j<3;j++){if(max<a[i][j])max=a[i][j];}printf("max=%d",max);}十一,矩阵对角线元素和#include<stdio.h>void main(){int i,j,m=0,a[3][3];for(i=0;i<3;i++)for(j=0;j<3;j++)scanf("%d",&a[i][j]);for(i=0;i<3;i++){for(j=0;j<3;j++)printf("a[%d][%d]=%2d ",i,j,a[i][j]);printf("\n");}printf("对角线之和为:");for(i=0;i<3;i++)m+=a[i][i];printf("%d",m);}十二,斐波那契数列#include<stdio.h>void main(){int fib[20]={1,1};int i;for(i=2;i<20;i++)fib[i]=fib[i-1]+fib[i-2];for(i=0;i<20;i++){if(i%5==0)printf("\n");printf("%5d",fib[i]);}}十三,杨辉三角#include<stdio.h>void main(){int a[10][10],i,j;for(i=0;i<10;i++){a[i][0]=1;a[i][i]=1;}for(i=2;i<10;i++)for(j=1;j<i;j++)a[i][j]=a[i-1][j]+a[i-1][j-1];for(i=0;i<10;i++){for(j=0;j<=i;j++)printf("%5d",a[i][j]);printf("\n");}}十四,101-200之间的素数#include<stdio.h>void main(){int sum,num,i;for(num=101;num<=200;num++){sum=0;for(i=2;i<num;i++){if(num%i==0)sum++;}if(sum==0)printf("%5d",num);}}#include<stdio.h>void main(){int i,j,k;for(i=0;i<=20;i++)for(j=0;j<=33;j++)for(k=0;k<=99;k=k+3)if((i+j+k==100)&&(15*i+9*j+k==300))printf("i=%d j=%d k=%d\n",i,j,k);}十六,猴子吃桃#include<stdio.h>void main(){int x1,x2=1,day;for(day=9;day>0;day--){x1=2*(x2+1);x2=x1;}printf("第一天的桃子数:%d\n",x1);5.1 用π/4≈1-1/3+1/5-1/7+…公式求π的值,直到某一项的绝对值小于10-6为止。
> 预处理器(Preprocessor)1. 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题)#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL我在这想看到几件事情:1). #define 语法的基本知识(例如:不能以分号结束,括号的使用,等等)2). 懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算一年中有多少秒而不是计算出实际的值,是更清晰而没有代价的。
3). 意识到这个表达式将使一个16位机的整型数溢出-因此要用到长整型符号L,告诉编译器这个常数是的长整型数。
4). 如果你在你的表达式中用到UL(表示无符号长整型),那么你有了一个好的起点。
记住,第一印象很重要。
2. 写一个“标准”宏MIN,这个宏输入两个参数并返回较小的一个。
#define MIN(A,B) ((A) <= (B) (A) : (B))这个测试是为下面的目的而设的:1). 标识#define在宏中应用的基本知识。
这是很重要的,因为直到嵌入(inline)操作符变为标准C的一部分,宏是方便产生嵌入代码的唯一方法,对于嵌入式系统来说,为了能达到要求的性能,嵌入代码经常是必须的方法。
2). 三重条件操作符的知识。
这个操作符存在C语言中的原因是它使得编译器能产生比if-then-else更优化的代码,了解这个用法是很重要的。
3). 懂得在宏中小心地把参数用括号括起来4). 我也用这个问题开始讨论宏的副作用,例如:当你写下面的代码时会发生什么事?least = MIN(*p++, b);3. 预处理器标识#error的目的是什么?如果你不知道答案,请看参考文献1。
这问题对区分一个正常的伙计和一个书呆子是很有用的。
只有书呆子才会读C语言课本的附录去找出象这种问题的答案。
当然如果你不是在找一个书呆子,那么应试者最好希望自己不要知道答案。
1.有1、2、3、4这四个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?解:#include<stdio.h>#include<conio.h>main(){int i,j,k;printf("\n");for(i=1;i<5;i++)for(j=1;j<5;j++)for(k=1;k<5;k++){if(i!=k&&i!=j&&j!=k)printf("%d,%d,%d\n",i,j,k);}getch();}2.企业发放的奖金根据利润提成。
利润I低于或等于10万元时,奖金可提成10%;利润高于10万元低于20万元时,低于10万元的部分按10%提成,高于10万元的部分可提7.5%;20万到40万之间时,高于20万的部分可提成5%,40万到60万之间时,高于40万的部分可提成3%;60万到100万之间时,高于60万元的部分可提成1.5%,高于100万元时,超过一百万元时按1%提成,从键盘输入当月利润I,求应发放奖金总数。
解:#include<stdio.h>main(){long int i;int bonus1,bonus2,bonus4,bonus6,bonus10,bonus;scanf("%ld",&i);bonus1=100000*0.1;bonus2=bonus1+100000*0.075;bonus4=bonus2+200000*0.05;bonus6=bonus4+200000*0.03;bonus10=bonus6+400000*0.015;if(i<=100000)bonus=i*0.1;else if(i<=200000)bonus=bonus1+(i-100000)*0.075;else if(i<=400000)bonus=bonus2+(i-200000)*0.05;else if(i<=600000)bonus=bonus4+(i-400000)*0.03;else if(i<=1000000)bonus=bonus6+(i-600000)*0.015;elsebonus=bonus10+(i-1000000)*0.01;printf("bouns=%d",bonus);getch();}3.一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少?解:#include<math.h>#include<stdio.h>#include<conio.h>main(){long int i,x,y;for(i=1;i<100000;i++){x=sqrt(i+100);y=sqrt(i+268);if(x*x==i+100&&y*y==i+268)printf("\n%ld\n",i);}getch();}4.输入某年某月,判断这一天是这一年的第几天。
大整数的乘法运算-C语言版在计算机中,长整型(long int)变量的范围是-2147483648 至2147483647,因此若用长整型变量做乘法运算,乘积最多不能超过10位数。
即便用双精度型(double)变量,也仅能保证16 位有效数字的精度。
在某些需要更高精度的乘法运算的场合,需要用别的办法来实现乘法运算。
比较容易想到的是做多位数乘法时列竖式进行计算的方法,只要写出模拟这一过程的程序,就能实现任意大整数的乘法运算。
经过查阅资料,找到一种更易于编程的方法,即“列表法”。
下面先介绍“列表法”:例如当计算8765 x 234时,把乘数与被乘数照如下列出,见表1:8 7 6 5 87652 16 14 12 10 23 24 21 18 15 34 32 28 24 20 4表1 表2把每个空格所在的行列的数字的乘积填入空格中,得表2。
把表2中的数按图示斜线分组(横纵坐标和相等的数分为一组),把每组数的累加起来所得的和记在表格下方,见表3:16 14 12 1024 21 18 1532 28 24 2016 38 65 56 39 20表3最后把表格下方一行数作如下处理,见表4:从最低位的20 开始,保留个位数字“0”,把个位以外的数“2”进到前一位;把次低位的39 加上低位进上来的2 得41,保留个位数字“1”,把“4”进到前一位;以此类推,直至最高位的16,16 加上低位进上来的4得20,保留“0”,把2进到最高位,得乘积答数2051010。
16 38 65 56 39 202 16+4=20 38+7=45 65+6=71 56+4=60 39+2=41留0进2 留5进4 留1进7 留0进6 留1进4 留0进22 0 5 1 0 1 0表4根据以上思路就可以编写C 程序了,再经分析可得:1、一个m 位的整数与一个n 位的整数相乘,乘积为m+n-1 位或m+n 位。
2、程序中,用三个字符数组分别存储乘数、被乘数与乘积。
由第1 点分析知,存放乘积的字符数组的长度应不小于存放乘数与被乘数的两个数组的长度之和。
3、可以把第二步“计算填表”与第三四步“累加进位”放在一起完成,可以节省存储表格2所需的空间。
4、程序关键部分是两层循环,内层循环累计一组数的和,外层循环处理保留的数字与进位。
编写的程序如下:程序1 清单:/* multiply.c *//* 11/20/2008 */#define MAXLENGTH 1000#include <stdio.h>#include <string.h>void compute(char *a, char *b, char *c);void main(void){char a[MAXLENGTH], b[MAXLENGTH], c[MAXLENGTH * 2];puts("Input multiplier :");gets(a);puts("Input multiplicand :");gets(b);compute(a, b, c);puts("Answer :");puts(c);getchar();}void compute(char *a, char *b, char *c){int i, j, m, n;long sum, carry;m = strlen(a) - 1;n = strlen(b) - 1;for (i = m; i >= 0; i--)a[i] -= '0';for (i = n; i >= 0; i--)b[i] -= '0';c[m + n + 2] = '\0';carry = 0;for (i = m + n; i >= 0; i--) /* i 为坐标和*/{sum = carry;if ((j = i - m) < 0)j = 0;for ( ; j<=i && j<=n; j++) /* j 为纵坐标*/sum += a[i-j] * b[j]; /* 累计一组数的和*/c[i + 1] = sum % 10 + '0'; /* 算出保留的数字*/carry = sum / 10; /* 算出进位*/}if ((c[0] = carry+'0') == '0') /* if no carry, */c[0] = '\040'; /* c[0] equals to space */}效率分析:用以上算法计算m位整数乘以n 位整数,需要先进行m x n次乘法运算,再进行约m+ n次加法运算和m + n次取模运算(实为整数除法)。
把这个程序稍加修改,让它自己产生乘数与被乘数,然后计算随机的7200位整数互乘,在Cyrix 6x86 pr166机器的纯DOS方式下耗时7秒(用Borland C3.1编译)。
经过改进,此算法效率可以提高约9 倍。
注意到以下事实:8216547 x 96785 将两数从个位起,每3位分为节,列出乘法表,将斜线间的数字相加;8 216 54796 785768 20736 525126280 169560 429395768 27016 222072 429395将表中最后一行进行如下处理:从个位数开始,每一个方格里只保留三位数字,超出1000 的分进位到前一个方格里;768 27016 222072 429395768+27 27016+222 222072+429=795 =27238 =222501 395795 238 501 395所以8216547 x 96785 = 795238501395也就是说我们在计算生成这个二维表时,不必一位一位地乘,而可以三位三位地乘;在累加时也是满1000进位。
这样,我们在计算m位整数乘以n位整数,只需要进行m x n / 9次乘法运算,再进行约(m + n) / 3次加法运算和(m + n) /3 次取模运算。
总体看来,效率约是前一种算法的9倍。
有人可能会想:既然能够三位三位地乘,为什么不4位4位甚至5位5位地乘呢?那不是可以提高16 乃至25 倍效率吗?听我解来:本算法在累加表中斜线间的数字时,如果用无符号长整数(范围0至~4294967295)作为累加变量,在最不利的情况下(两个乘数的所有数字均是9),能够累加约4294967295/(999*999)=4300 次,也就是能够准确计算任意两个均不超过12900(每次累加的结果"值"三位,故4300*3=12900)位的整数相乘。
如果 4 位 4 位地乘,在最不利的情况下,能够累加约4294967295/(9999*9999)=43 次,仅能够确保任意两个不超过172 位的整数相乘,没有什么实用价值,更不要说5位了。
请看改进后的算法的实例程序:该程序随机产生两个72xx位的整数,把乘数与积保存在result.txt中。
在Borland C++ 3.1 中用BCC -3 -O2 -G -mh -Z -f287 -pr -T- dashu.cpp编译生成的exe文件在Cyrix 6x86 pr166的机器上运行耗时0.82 秒。
程序2 清单:#include<conio.h>#include<string.h>#include<stdio.h>#include<stdlib.h>#include<time.h>#define N 7200 //作72xx 位的整数乘法int max(int,int,int);int initarray(int a[]);void write(int a[],int l);FILE *fp;void main()int a[5000]={0},b[5000]={0},k[10001]={0}; //声明存放乘数、被乘数与积的数组clock_t start, end; //声明用于计时的变量unsigned long c,d,e; //声明作累加用的无符号长整数变量int i,j,la,lb,ma,mi,p,q,t; //声明其它变量randomize(); //初始化随机数la=initarray(a); //产生被乘数,并返回其长度lb=initarray(b); //产生乘数,并返回其长度if(la<lb) //如果被乘数长度小于乘数,则交换被乘数与乘数{p=(lb>la)?lb:la;for (q=0;q<p;q++) //交换被乘数与乘数t=a[q],a[q]=b[q],b[q]=t;t=la,la=lb,lb=t; //交换被乘数的长度与乘数的长度}start = clock();//开始计时c=d=0; //清空累加变量,其中C 用于累加斜线间的数,d 用作进位标志for(i=la+lb-2;i>=0;i--) //累加斜线间的数,i 为横纵坐标之和{c=d; //将前一位的进位标志存入累加变量cma=max(0,i-la+1,i-lb+1); //求累加的下限mi=(i>la-1)?(la-1):i; //求累加的上限for(j=ma;j<=mi;j++) //计算出横纵坐标之和为i 的单元内的数,并累加到C 中c+=(long)a[j]*b[i-j];d=c/1000; //求进位标志if(c>999)c%=1000; //取c 的末三位k[i]=c; //保存至表示乘积的数组k[]}e=k[0]+1000*d; //求出乘积的最高位end = clock();//停止计时fp = fopen("result.txt", "w+"); //保存结果到result.txtprintf("\nThe elapsed time was: %3.4f\n", (end - start) / CLK_TCK);//打印消耗的时间fprintf(fp,"%d",a[0]); //打印被乘数最高位write(a,la); //打印被乘数其他位fprintf(fp,"%d",b[0]); //打印乘数最高位write(b,lb); //打印乘数其他位fprintf(fp,"%ld",e); //打印乘积最高位write(k,la+lb-1); //打印乘积其他位fclose(fp);}max(int a,int b,int c){int d;d=(a>b)?a:b;return (d>c)?d:c;}int initarray(int a[]){int q,p,i;q=N+random(100);if(q%3==0)p=q/3;elsep=q/3+1;for(i=0;i<p;i++)a[i]=random(1000);if(q%3==0)a[0]=100+random(900);if(q%3==2)a[0]=10+random(90);if(q%3==1)a[0]=1+random(9);return p;}void write(int a[],int l){int i;char string[10];for(i=1;i<l;i++){itoa(a[i],string,10);if (strlen(string)==1)fprintf(fp,"00");if (strlen(string)==2)fprintf(fp,"0");fprintf(fp,"%s",string);if((i+1)%25==0)fprintf(fp,"\n");}fprintf(fp,"\n");fprintf(fp,"\n");}。