题目描述:

输出两个不超过100位的大整数的乘积。

输入:

输入两个大整数,如1234567 123

输出:

输出乘积,如:151851741

样例输入:

1234567 123

样例输出:

151851741

注意:在oj上不能直接套用我的代码,需要将无关的输出去除才行

方法一

思路:

解这道题目最简单的方法就是模拟我们笔算乘法的过程,如:1234×123

只要把这个过程实现,无论多大的数我们都能解决了,是不是很简单。

程序实现:

首先,我们用两个字符串来保存我们的大整数,num1[100], num2[100]

scanf("%s%s", num1, num2);

然后,求num2的每一位与num1的乘积,保存到tempRes中。

过程为:res保存每位相乘的结果,carry用来保存进位,每位相乘之后还要加上进位才是真的结果。将res的个位保存到tempRes中,其他位则为下一位相乘的进位。

for(j = num2Len - ; j >= ; j--)

{

/*计算num1与num2各位相乘的结果,保存到tempRes中

*每一位相乘后与之前的进位相加得出res,将res的个

*位(res%10)保存到tempRes里,然后将res的其余位数

*(res/10)则为进位carry*/

for(i = num1Len-; i >= ; i--)

{

res = Int(num1[i]) * Int(num2[j]) + carry;

tempRes[tempResLen--] = Char(res % );

carry = res / ;

}

//tempRes第一位为进位,刚刚的循环是没有算的,最后把进位算上

tempRes[tempResLen] = Char(carry);

tempResLen = num1Len;

carry = ;

}

再然后,将tempRes与result求和,每求一次,向左偏移一位。res为每位之和再加上进位,这里很重要,然后保存到result里只是res的个位,res为下一位计算的进位。

//由result的末尾开始计算和,算完一次,向左偏移一位

for(k = resultLen-offset; k > (resultLen-offset-num1Len); k--)

{

res = Int(result[k]) + Int(tempRes[tempResLen--]) + carry;

result[k] = Char(res%);

carry = res/;

}

result[k] += Int(tempRes[tempResLen] + carry);

offset++;

以上两步就是我程序最核心的部分。以下是程序的全部代码。

#include

#include

#include

#define and &&

#define or ||

#define not !

#define Int(X) (X - '0')

#define Char(X) (X + '0')

char *multiBigInteger(const char *, const char *);

int checkNum(const char *);

int main(void)

{

char num1[] = {'\0'}, num2[] = {'\0'};

while(scanf("%s%s", num1, num2) != EOF)

{

char *result = "";

if(strlen(num1) > or strlen(num2) > )

{

printf("ERROR\n");

return ;

}

if(checkNum(num1) or checkNum(num2))

{

printf("ERROR: input must be an Integer\n");

return ;

}

printf("num1:\t%s\nnum2:\t%s\n", num1, num2);

result = multiBigInteger(num1, num2);

if(result[] == '')

{

int i;

printf("result:\t");

for(i = ; (size_t)i < strlen(result); i++)

{

printf("%c", result[i]);

}

printf("\n");

}

else

{

printf("result:\t%s\n", result);

}

printf("\n");

}

return ;

}

int checkNum(const char *num)

{

int i;

for(i = ; (size_t)i < strlen(num); i++)

{

if(num[i] < '' or num[i] > '')

{

return ;

}

}

return ;

}

char *multiBigInteger(const char *num1, const char *num2)

{

char *tempRes = NULL; //用来保存每次相乘的结果

char *result = NULL; //用来保存最终结果

int tempResLen; //每次相乘结果的最大长度

int num1Len = strlen(num1); //num1的长度

int num2Len = strlen(num2); //num2的长度

int resultLen; //结果的最大长度

int i, j, k; //循环计数器

int res; //每次一位相乘/相加的结果

int carry = ; //进位

int offset = ; //加法的偏移位

resultLen = num1Len + num2Len - ; //结果长度最大为num1长度和num2长度之和,由于下标从0开始,所以要减一

tempResLen = num1Len; //每次num1乘以num2每一位的结果最大长度是num1Len+1,由于下标从0开始,所以减一后约去1,只剩num1Len

//初始化result为0

result = (char *)malloc((resultLen+)*sizeof(char));

memset(result, '', (resultLen+)*sizeof(char));

result[resultLen+] = ;

tempRes = (char *)malloc((tempResLen+)*sizeof(char));

for(j = num2Len - ; j >= ; j--)

{

//初始化tempRes每位为0

memset(tempRes, '', (tempResLen+)*sizeof(char));

/*计算num1与num2各位相乘的结果,保存到tempRes中

*每一位相乘后与之前的进位相加得出res,将res的个

*位(res%10)保存到tempRes里,然后将res的其余位数

*(res/10)则为进位carry*/

for(i = num1Len-; i >= ; i--)

{

res = Int(num1[i]) * Int(num2[j]) + carry;

tempRes[tempResLen--] = Char(res % );

carry = res / ;

}

//tempRes第一位为进位,刚刚的循环是没有算的,最后把进位算上

tempRes[tempResLen] = Char(carry);

tempResLen = num1Len;

carry = ;

//由result的末尾开始计算和,算完一次,向左偏移一位

for(k = resultLen-offset; k > (resultLen-offset-num1Len); k--)

{

res = Int(result[k]) + Int(tempRes[tempResLen--]) + carry;

result[k] = Char(res%);

carry = res/;

}

result[k] += Int(tempRes[tempResLen] + carry);

carry = ;

tempResLen = num1Len;

offset++;

}

printf("num1Len:%d\nnum2Len:%d\n", num1Len, num2Len);

return result;

}

大整数相乘完整代码

以下是程序执行的结果:

看了以上的代码,感觉思路虽然很简单,但是实现起来却很麻烦,那么我们有没有别的方法来实现这个程序呢?答案是有的,接下来我来介绍第二种方法。

方法二:

思路:

简单来说,方法二就是先不算任何的进位,也就是说,将每一位相乘,相加的结果保存到同一个位置,到最后才计算进位。

例如:result[200]用来保存结果,计算98×21,步骤如下

由上面可以看出,result的数据为result[100] = {0, 18, 27, 9}

接下来就处理进位,注意看,巧妙的地方来了:

有result末尾到首位计算:

第一次:result[3] = 9; result[2] = 27;

A.先将result[3]除个位以外的数加给前一位,也就是result[2]:result[2] = result[2]+result[3]/10 = 27 + [9/10]=27; 注:数学里面的[]为取整符。如[0.9] = 0

B.然后把result[3]的个位保存到result[3]:

>> result[3] = result[3]%10 = 9;

第二次,向前一位,result[2] = 27, result[1] = 18;

重复第一次的A、B步骤,求得result[1] = result[1]+result[2] / 10=18+[27/10] = 20;

>> result[2] = result[2] % 10 = 7

第三次,再向前一位,result[1] = 20, result[0] = 0

重复之前的步骤,

>> result[0] = result[0]+result[1]/10=0+[20]/10=2

>> result[1] = result[1] % 10 = 0;

至此,已经算到首位,result此时的结果为:result[100] = {2, 0, 7, 9}可以知道这就是结果:99×21=2079;

核心代码:

先是不进位的各位之和:

for(j = ; j < num2Len; j++)

{

for(i = ; i < num1Len; i++)

{

/* result第一位是用来保存result长度的,而第二位是保存结果最后的进位的

* 没有进位,则result[1]为0,所以每位相乘之和是从第三位(即result[2])

* 开始。这里是本程序的比较巧妙的地方,需要仔细想想。

* */

result[i+j+] += Int(num1[i]) * Int(num2[j]);

}

}

接下来是处理进位的代码:

/* 这个循环用来处理进位的,所以要从result的最后一位一直处理到首位。

* 要注意result的总长度是resultLen+1,有一位是保存result的长度,而

* C语言下标是从0开始,所以result的最后一位的下标就是resultLen,而

* 第一位就是1。*/

for(i = resultLen; i > ; i--)

{

result[i-] += result[i]/;

result[i] = result[i]%;

}

注意:这个方法有一个大坑,就是保存结果的result的数据类型必须至少是int,而不能是char,为什么呢?先想想再打开答案。

/* 因为char类型的数据每个只有1个字节

* 也就是8位,所以保存的最大数值为256

* 而我们这个程序,每位最大为100个9×9=81

* 之和,也就是每个数据必须最大要能保存的数

* 值为8100, 所以char数据类型就不够保存了。

* good luck :-)*/

答案

接下来程序的完整代码:

#include

#include

#include

#define and && /**************/

#define or || /* python风格 */

#define not ! /* */

#define Int(X) (X - '0') /**************/

int *multiBigInteger(const char *, const char *);

int checkNum(const char *);

int main(void)

{

char num1[] = {'\0'}, num2[] = {'\0'};

printf("Please input two nunber(less than 100 digits):\n> ");

while(scanf("%s%s", num1, num2) != EOF)

{

int *result = NULL;

int i, change = ;

//对输入的数据进行检验

if(strlen(num1) > or strlen(num2) > )

{

printf("per number must less than 100 digits\n");

return ;

}

if(checkNum(num1) or checkNum(num2))

{

printf("ERROR: input must be an Integer\n");

return ;

}

printf("num1:\t%s\nnum2:\t%s\n", num1, num2);

result = multiBigInteger(num1, num2);

/* 输出结果result,result[0]保存着result的长度,

* 所以下标要从1开始 */

printf("result:\t");

for(i = ; i <= result[]; i++)

{

if(result[i] != ) //这一步用来去掉前导0,第一位为0跳过不输出

change = ;

if(not change)

{

if(i > ) //这一步用来判断结果是否为0,

{ //如果结果第二位还是0,就判断为0

printf("");

break;

}

continue;

}

printf("%d", result[i]);

}

printf("\n");

printf("\nPlease input two nunber(less than 100 digits):\n> ");

}

return ;

}

//用于检测输入的是否是数字,如果是就返回0,不是就返回1

int checkNum(const char *num)

{

int i;

for(i = ; (size_t)i < strlen(num); i++)

{

if(num[i] < '' or num[i] > '')

{

return ;

}

}

return ;

}

//返回结果result,为一片内存块,类似数组

int *multiBigInteger(const char *num1, const char *num2)

{

int *result = NULL; //用来保存最终结果

int num1Len = strlen(num1); //num1的长度

int num2Len = strlen(num2); //num2的长度

int resultLen; //结果的最大长度

int i, j; //循环计数器

resultLen = num1Len + num2Len; //结果长度最大为num1长度和num2长度之和

//初始化result为0

result = (int *)malloc((resultLen+)*sizeof(int));

memset(result, , (resultLen+)*sizeof(int));

result[] = resultLen; //result的第一位是用来保存result的长度的。

/* num1乘以num2,由于这里采用先不进位的算法,所以算法是按从左到右

* 按顺序来乘,然后将每位的结果保存到result的每一位中,循环一次

* reult就从下一位开始求和。如下:(左边为正常算法,右边为本程序算法)

*

* 54321 | 54321

* × 123 | × 123

* ------- | --------

* 162963 | 54321

* 108642 | 108642

* 54321 | 162963

* -------- | ---------

* 6681483 | 6681483

*

* */

for(j = ; j < num2Len; j++)

{

for(i = ; i < num1Len; i++)

{

/* result第一位是用来保存result长度的,而第二位是保存结果最后的进位的

* 没有进位,则result[1]为0,所以每位相乘之和是从第三位(即result[2])

* 开始。这里是本程序的比较巧妙的地方,需要仔细想想。

* */

result[i+j+] += Int(num1[i]) * Int(num2[j]);

}

}

/* 这个循环用来处理进位的,所以要从result的最后一位一直处理到首位。

* 要注意result的总长度是resultLen+1,有一位是保存result的长度,而

* C语言下标是从0开始,所以result的最后一位的下标就是resultLen,而

* 第一位就是1。*/

for(i = resultLen; i > ; i--)

{

result[i-] += result[i]/;

result[i] = result[i]%;

}

printf("num1Len:%d\nnum2Len:%d\n", num1Len, num2Len);

return result;

}

大整数相乘2完整代码

程序运行结果:

总结:

这是一道非常经典而且必须要掌握的题目,所以看到这篇文章的你最好能认真理解一下。

作者:陈栋权

时间:2016/09/17

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,

且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

最后有兴趣的同学可以关注我的微信公众号,可以随时及时方便看我的文章。*^_^*

扫码关注或者搜索微信号:King_diary

华为OJ机试训练(一)

题目1 -- 通过输入英文句子.将每一个单词反过来,标点符号顺序不变.非26个字母且非标点符号的情况就可以标识单词结束. 标点符号包含,.!? 比如输入:Hello, I need an apple. ...

华为 2015 机试 输出:数字后面的连续出现的(2个或多个)相同字符(数字或者字符),删去一个,非数字后面的不要删除,例如,对应输出为:33aabb55pin。

package 华为机试; //C++ 输入:由数字和字母组成的字符串,例如:333aaabb55ppin //输出:数字后面的连续出现的(2个或多个)相同字符(数字或者字符),删去一个,非数字后面的 ...

华为JAVA机试流程

1.JAVA机试流程:①打开IE浏览器,输入机试系统IP地址(以当天告知的地址为准):②输入姓名.手机,选择“C/C++”或“JAVA”,登录:③登录后显示题目,阅读题目并点击页面最下方的“下载框架文 ...

Hua Wei 机试题目三---2014

一.根据对应规则进行翻译输出 描述:已知有如下的对应规则: ,则输入任意个正整数,输出经过规则翻译以后对应的结果. 例如:输入:1234:输出bcde. 题目很简单,我觉得需要注意的问题就是对于大整数 ...

九度oj 题目1083:特殊乘法 清华大学2010年机试题目

题目描述: 写个算法,对2个小于1000000000的输入,求结果. 特殊乘法举例:123 * 45 = 1*4 +1*5 +2*4 +2*5 +3*4+3*5 输入: 两个小于1000000000的 ...

九度oj 题目1085:求root&lpar;N&comma; k&rpar; 清华2010年机试题目

题目描述: N

9月5日 华为2014校园招聘的机试题目&lowbar;C语言版答案

手有些生了. 题目: 通过键盘输入一串小写字母(a~z)组成的字符串.请编写一个字符串压缩程序,将字符串中连续出席的重复字母进行压缩,并输出压缩后的字符串.压缩规则:1.仅压缩连续重复出现的字符.比如 ...

一道来自华为的C机试题目

题目是这样的 求一个字符串中连续字母的个数 比如I have a book. : 1 I have a dog. : 0 I haavee aa dogg : 4 #include

华为2013年西安java机试题目:如何过滤掉数组中的非法字符。

这道题目为记忆版本: 题目2描述: 编写一个算法,过滤掉数组中的非法字符,最终只剩下正式字符. 示例:输入数组:“!¥@&HuaWei*&%123” 调用函数后的输出结果,数组:“Hu ...

随机推荐

html中submit和button的区别&sol; window&period;location&period;href 不跳转 的问题

这两个的区别 是 button 不会自动提交表 ...

&lbrack;洛谷OJ&rsqb; P1114 &OpenCurlyDoubleQuote;非常男女”计划

洛谷1114 “非常男女”计划 本题地址:http://www.luogu.org/problem/show?pid=1114 题目描述 近来,初一年的XXX小朋友致力于研究班上同学的配对问题(别想太 ...

Java 入门 代码2浮点数据类型

/** * 基本数据类型之浮点类型 */ public class DataTypeDemo2 { public static void main(String[] args) { double d1 ...

HTTPS-能否避免流量劫持

流量劫持是什么? EtherDream在一篇科普文章<>中详细介绍了流量劫持途径和方式. 流量劫持是一种古老的攻击方式,比如早已见惯的广告弹窗等,很多人已经对此麻木,并认为流量劫持不会造成 ...

使用Kinect2&period;0获取点云以在GLUT中显示

这篇文章用来记录Kinect2.0如何生成点云. 以下示例源自Kinect提供的example修改完成,其名称会在小标题下方注解. 首先,要获取点云需要获取图像的深度数据和颜色数据.最后再将深度数据与 ...

PHP请求页面

< ?php $file_contents = file_get_contents('http://www.ccvita.com/'); echo $file_contents; ?> 有 ...

Java8新特性 1——利用流和Lambda表达式操作集合

Java8中可以用简洁的代码来操作集合,比如List,Map,他们的实现ArrayList.以此来实现Java8的充分利用CPU的目标. 流和Lambda表达式都是Java8中的新特性.流可以实现对集 ...

SDUT 最短路径(二维SPFA)

http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2622 #include

家居环境监測系统设计(PC上位机版)(手机APP版待定)

下面是我的毕业设计:家居环境监測系统设计(PC上位机临时版.手机app版待定).本系统採用STC12C5A60S2单片机.结合传感器.分别对空气湿度.空气温度.气压.海拔.进水温度.出水温度.光照强度 ...

解析PHP程序员需要掌握的必备技能

转自:http://www.php100.com/html/php/lei/2013/0904/4199.html 作为PHP的爱好者,如果你想加入PHP程序的世界,一定要做好充分的准备.建议大家阅读 ...

循环相乘取整法C语言,华为OJ机试题目:两个大整数相乘(纯C语言实现两个大整数相乘,两种方法实现大数相乘)...相关推荐

  1. 华为oj题目c语言,华为OJ机试题目——24点游戏算法

    对于这种题用程序实现只能是穷举的思想,而做法各异,如下代码是利用符号的不断变化,利用4个数计算值,默认是4个数字a,b,c,d是按顺序计算的,即默认是加了括号的,即(((a op1 b)op2 c)o ...

  2. C语言无符号双字节乘法,华为OJ机试标题:两个大整数相乘(纯C语言实现两个大整数相乘,两种方法实现大数相乘)...

    华为OJ机试题目:两个大整数相乘(纯C语言实现两个大整数相乘,两种方法实现大数相乘) 题目描述: 输出两个不超过100位的大整数的乘积. 输入: 输入两个大整数,如1234567 123 输出: 输出 ...

  3. 2018华为校招机试题目练习

    1.数字处理 题目描述:给出一个不多于5位的整数,进行反序处理,要求 (1)求出它是几位数 (2)分别输出每一个数字(空格隔开) (3)按逆序输出各位数字(仅数字间以空格间隔,负号与数字之间不需要间隔 ...

  4. 2018华为校招机试题目

    华为机试一共3道题,第1题100分,第2题200分,第3题300分,满分600分.考试时间为两个小时.想拿sp,当然要全部AC了. 1.数字处理 题目描述:给出一个不多于5位的整数,进行反序处理,要求 ...

  5. 2023华为od机试真题【简易内存池】C语言

    请实现一个简易内存池,根据请求命令完成内存分配和释放. 内存池支持两种操作命令,REQUEST和RELEASE,其格式为: REQUEST=请求的内存大小 表示请求分配指定大小内存,如果分配成功,返回 ...

  6. 2023华为OD机试真题目录 B卷,使用C语言进行解答

    文章目录

  7. 华为博士招聘上机考试题目_华为招聘机试题目

    2012 届华为校园招聘上机考试题目( 9 月 6 日下午 1 点场) 昨天去参加了华为的校园招聘上机考试,题目一共三道,都比较简单,不要求 算法效率, 也不要求对所给数据的合法性作检测, 主要还是注 ...

  8. 2016华为校招机试题目02

    题目: 开发一个简单错误记录功能小模块,能够记录出错的代码所在的文件名称和行号.  处理: 1.记录最多8条错误记录,对相同的错误记录(即文件名称和行号完全匹配)只记录一条,错误计数增加:(文件所在的 ...

  9. 华为2012机试题目及解答程序(仅供参考,版权归华为所有)

    题目:(原来是VC++ 6.0的环境,此处修改为简单cpp文件,不需要func.h文件 /* 请在这里实现下列函数, c c++语法不限, 最后需要保证程序编译连接通过, 并生成test.exe文件. ...

最新文章

  1. vue项目持久化存储数据的实现代码
  2. docker 容器 导入 导出
  3. Python Inotify 监视LINUX文件系统事件
  4. 支付宝 .NET SDK 报错:RSA签名遭遇异常,请检查私钥格式是否正确。
  5. hibernate左连接查询时在easyUI的dataGrid中有些行取值为空的解决办法
  6. React开发(249):react项目理解 ant design input loading
  7. 【电子书】Head First Java
  8. Godot Label 节点
  9. 用c语言判断一个数是否是素数(质数)
  10. 使用python对图片进行压缩
  11. mysql数据库 uft8_unicode_ci是utf8吗_mysql utf8_unicode_ci与utf8_general_ci的区别
  12. React18 tearing tree issue 撕裂状态问题
  13. 纵即逝的烟花蓄势于纸
  14. 惠普暗影精灵8Pro和联想拯救者Y9000P哪个好
  15. v4l2架构专题模块handler分析 -- handler ctrl的注册2
  16. PASCAL VOC目标检测数据集格式转化为COCO目标检测数据集格式
  17. Laravel使用swagger PHP生成api接口文档
  18. iptables匹配multiport
  19. 惠普HP LaserJet Pro P1606dn 打印机驱动
  20. 推荐6本入门Python数据分析公认的必看经典教材

热门文章

  1. Len()、Lenw()与Lenb()函数间的区别
  2. php 排序指定key,php实现数组按指定KEY排序的方法
  3. IDEA不支持SQL语法校验,一招搞定
  4. 软考高级信息系统项目管理师必备知识点(记忆敲出)
  5. Dyna中建立预紧力螺栓的两种方法
  6. Python编程:sh模块执行shell命令
  7. Flutter安装时你一定会碰到的问题
  8. 10路智能电动自行车充电桩功能特点优势
  9. 十年,AMD“三剑合一”再出击
  10. 缔造企鹅:产品经理是这样炼成的札记-技巧