Linux C/C++ 编程练手 --- 大数相加和大数相乘
最近写了一个大数相乘和相加的程序,结果看起来是对的。不过期间的效率可能不是最好的,有些地方也是临时为了解决问题而直接写出来的。
可以大概说一下相乘和相加的解决思路(当然,大数操作基本就是两个字符串的操作了):
一、思路:
在操作大数前,一定会有一些异常判断,比如输入的字符串是否合法(是否是纯数字?是否为空?等等),然后才是具体的操作实现:
1、大数相加(大体思路:将大数相加问题,转换成十以内的两数相加):
①申请合适的空间,一般可以认定,两个数字相加时,长度至多是最长的数的长度或最长的数的长度加1;
②从个位(字符串中就是从最后一位)开始,进行逐位相加;
③每位相加后,立即判断是否有进位,再将本次计算的个位数字记录到result字符串中;
④当短字符串过完后,按照同样的方式,过完长字符串的剩余数字;
⑤长字符串过完后,判断是否存在进位,如果有,则最后再赋值到result字符串中,如果没有,则最后将0(也就是结束符)赋值到result字符串中;
⑥由于操作的result字符串是倒置操作的,最后再把字符串逆置,返回即为两数相加结果;
2、大数相乘(大体思路:将大数相乘问题,转换成十以内的两数相乘):
①按照一般的两数相乘的思路,运算过程中,会产生一个二维数组样式的中间结果(准确点是一个字符串数组),数组的行数是第二个数字的个数;
②每次得出这个字符串数组的一行的结果,具体为:
a、针对这个字符串数组,每次运算前,申请合适的空间,一般可以认定,一个数和一个十以内的数字相乘时,长度至多是该数的长度或该数长度加1;但是还有一点需要考虑到,从十位开始,数字相乘后,默认是在最后加0的,规律为十位对应1个0,百位对应2个0,以此类推。因此需要申请的空间除了该数的长度加1外,还需要加上本次操作需要额外增加的0的个数;
b、在数字真正相乘前,需要将对应的0进行补齐(即个位数相乘时增加0个0,十位数相乘时增加1个0 ... ... )
c、每次取出第二个数的一个数字,取出顺序为倒序(从个位开始),然后与第一个数字进行逐位相乘;
d、相乘结果判断进位,并且保存,此次乘出来的结果保留个位数字,放入到本行的字符串结果中;
e、过完第一个数字的长度后,判断是否有进位,有的话则直接将进位赋值到本行字符串结果中,没有的话则将0赋值到本行字符串结果中;
f、然后循环进行,直到将第二个数字过完后,就会产出一个二维数组(或称之为字符串数组);
③最后把这个字符串数组的每一行相加(用到上面的大数相加函数来做),就是最终的相乘结果;
二、代码:
1、大数相加:
char *BigNumSum(char *bignum1, char *bignum2)
{
char *result, *big, *small;
int bignum1_length = strlen(bignum1);
int bignum2_length = strlen(bignum2);
int bigger, smaller; if(bignum1_length >= bignum2_length)
{
bigger = bignum1_length;
smaller = bignum2_length;
big = bignum1;
small = bignum2;
}
else
{
bigger = bignum2_length;
smaller = bignum1_length;
big = bignum2;
small = bignum1;
} int tmp, tmp_gewei, tmp_jinwei = 0, num = 0;
result = (char *)malloc(sizeof(char) * (bigger + 1));
for(int i = smaller - 1, j = bigger - 1; i >= 0 && j >= 0; i--, j--)
{
char *tmp_big = ctocs(big[j]);
char *tmp_small = ctocs(small[i]);
tmp = atoi(tmp_big) + atoi(tmp_small) + tmp_jinwei;
tmp_gewei = tmp % 10;
tmp_jinwei = tmp / 10;
result[num++] = tmp_gewei + ASICNUM;
}
for(int i = bigger - smaller - 1; i >= 0; i--)
{
char *tmp_big = ctocs(big[i]);
tmp = atoi(tmp_big) + tmp_jinwei;
tmp_gewei = tmp % 10;
tmp_jinwei = tmp / 10;
result[num++] = tmp_gewei + ASICNUM;
}
if(tmp_jinwei > 0)
{
result[num] = tmp_jinwei + ASICNUM;
}
else
{
result[num] = 0;
}
recover(result);
return result;
}
2、大数相乘:
char *BigNumMultip(char *bignum1, char *bignum2)
{
char *result;
int bignum1_length = strlen(bignum1);
int bignum2_length = strlen(bignum2); char *tmp[bignum2_length];
int i;
for(i = bignum2_length - 1; i >= 0; i--)
{
int t;
int j;
tmp[i] = (char *)malloc(sizeof(char) * (bignum1_length + 1 + (bignum2_length -1 - i)));
for(t = 0; t < bignum2_length -1 - i; t++)
tmp[i][t] = 0 + ASICNUM;
int tmp_jinwei = 0;
for(j = bignum1_length - 1; j >= 0; j--)
{
char *tmp_bignum1 = ctocs(bignum1[j]);
char *tmp_bignum2 = ctocs(bignum2[i]);
int tmp_multip = atoi(tmp_bignum1) * atoi(tmp_bignum2) + tmp_jinwei;
int tmp_gewei = tmp_multip % 10;
tmp_jinwei = tmp_multip / 10;
tmp[i][t++] = tmp_gewei + ASICNUM;
}
if(tmp_jinwei > 0)
{
tmp[i][t] = tmp_jinwei + ASICNUM;
}
else
{
tmp[i][t] = 0;
}
recover(tmp[i]);
// puts(tmp[i]);
}
result = (char *)malloc(sizeof(char) * (strlen(tmp[i+1]) + 1));
memset(result, '0', strlen(result));
for(int i = 0; i < bignum2_length; i++)
{
result = BigNumSum(tmp[i], result);
} return result;
}
3、其他:
①字符串逆置:
void recover(char *string)
{
int length = strlen(string);
int tmp;
for(int i = 0; i < length / 2; i++)
{
tmp = string[i];
string[i] = string[length - i - 1];
string[length - i - 1] = tmp;
}
}
②判断是否是数字字符串:
bool isDigital(char *string)
{
bool ret = true;
int length = strlen(string); for(int i = 0; i < length; i++)
{
if(string[i] < '0' || string[i] > '9')
{
ret = false;
break;
}
}
return ret;
}
③字符转换为字符串:
char *ctocs(char ch)
{
char *a;
a = (char *)malloc(sizeof(char) * 2);
a[0] = ch;
a[1] = 0; return a;
}
④main函数调用:
int main(int argc, char **argv)
{
if(3 != argc)
{
printf("error\n");
return 1;
}
char *bignum1 = argv[1];
char *bignum2 = argv[2]; bool ret1 = isDigital(bignum1);
bool ret2 = isDigital(bignum2); if(false == ret1 || false == ret2)
{
printf("input not number\n");
return 2;
}
char *multip_result = BigNumMultip(bignum1, bignum2);
char *sum_result = BigNumSum(bignum1, bignum2); printf("数字 1:%s\n数字 2:%s\n两数积:%s\n两数和:%s\n", bignum1, bignum2, multip_result, sum_result);
return 0;
}
这段代码也就是按照一个最基本的思路进行简单的实现,基本如上,没有太多注释,目前可以预见到的问题就是:①执行效率、②内存消耗;后面有空会再进行优化的~
目前测试了一些数字,是可以正确返回的(当然,太大的数字也就是验证的后面或前面的几位的数字)。如果大家有发现不对有有问题的地方,求指点~
Linux C/C++ 编程练手 --- 大数相加和大数相乘的更多相关文章
- 好记性不如烂笔头--linux学习笔记9练手写个shell脚本
#!/bin/bash #auto make install httpd #by authors baker95935 #httpd define path variable H_FILES=http ...
- HDU 1316 (斐波那契数列,大数相加,大数比较大小)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1316 Recall the definition of the Fibonacci numbers: ...
- Java 大数相乘、大数相加、大数相减
思路来源:: https://blog.csdn.net/lichong_87/article/details/6860329 /** * @date 2018/6/22 * @description ...
- 大数相加和大数相乘以及打印从1到最大的n位数
string add(string a, string b){ int nlength; int diff; if (a.size() > b.size()){ nlength = a.size ...
- JAVA大数类练手
今天突然看到了OJ上的大数类题目,由于学习了一点大数类的知识.果断水了6道题......都是非常基础的.就当的练手的吧. 学到的只是一些大数类的基本操作.以后多做点这样的题,争取熟练运用水大数题... ...
- Python之路【第二十四篇】:Python学习路径及练手项目合集
Python学习路径及练手项目合集 Wayne Shi· 2 个月前 参照:https://zhuanlan.zhihu.com/p/23561159 更多文章欢迎关注专栏:学习编程. 本系列Py ...
- 10个有趣的Python教程,附视频讲解+练手项目。
从前的日色变得慢,车.马.邮件都慢 一生只够爱一门编程语言 从前的教程也好看,画面精美有样子 你看了,立马就懂了 Python最性感的地方,就在于它的趣味性和前沿性,学习Python,你总能像科技节的 ...
- 【Python精华】100个Python练手小程序
100个Python练手小程序,学习python的很好的资料,覆盖了python中的每一部分,可以边学习边练习,更容易掌握python. [程序1] 题目:有1.2.3.4个数字,能组成多少个互不相同 ...
- 整理了适合新手的20个Python练手小程序
100个Python练手小程序,学习python的很好的资料,覆盖了python中的每一部分,可以边学习边练习,更容易掌握python. 本文附带基础视频教程:私信回复[基础]就可以获取的 [程序1] ...
随机推荐
- 对整站的a链接进行监控,对匹配规则进行指定页面的跳转
项目中有个需求,就是将非本站的链接跳转到过渡页(提示即将离开本站的那种页面).这个时候想起了腾讯邮箱,不安全链接会有新的页面提示,如下图: 本以为ASP.NET中有全局的方法获取到点击或者跳转的链接, ...
- qml实现自定义标题栏按钮
自定义的标题栏按钮是由Rectangle来实现的,在Rectangle中需要4张图片,分别在鼠标进入按钮区.鼠标离开按钮区(正常状态下).鼠标按下和鼠标释放时所加载的图片.下面是实现自定义按钮的代码( ...
- javascript常用对象
A,window对象 window对象是浏览器模型对象的顶层对象 常用属性: screen:客户端的屏幕和显示性能的信息. history:客户端访问过的url信息 location:当前url链接的 ...
- 几个好用的截取字符串的php函数分享
分享几个好用的PHP 截取字符串函数(支持gb2312和utf-8). 1.截取GB2312字符用的函数 <?php /** **截取中文字符串 * edit by www.jbxue.com ...
- phpcms v9 打开网站特别慢 增加数据库缓存方法
SET GLOBAL QUERY_CACHE_SIZE=80000000; 设置好查询缓存的大小就行了.比如设置个20MB.SET GLOBAL QUERY_CACHE_SIZE=20000000; ...
- 解决java.io.IOException: Cannot run program "cygpath": CreateProcess error=2, 系统找不到指定的文件 的错误
一.外部环境: 系统环境:Windows 8 磁盘分区:只有C盘 开发环境:IntelliJ IDEA Community Edition 2016.1.3(64) 执行代码:rdd.saveAsTe ...
- Python试卷
3.写一个函数,计算一个给定的日期是该年的第几天. def getday(self,y=None,m=None,d=None): date = datetime(y,m,d) days = date. ...
- Oracle表连接
一个普通的语句select * from t1, t2 where t1.id = t2.id and t1.name = 'a'; 这个语句在什么情况下最高效? 表连接分类: 1. 嵌套循环连接(N ...
- 【学习总结】IOS程序运行过程 、UIWindow 、controller 、 UIView 创建过程的总结
程序启动开始到view显示: 程序启动首先会执行main函数 - > UIApplicationMain函数: 程序启动 (加载框架,info文件,资源等) 执行Main函数 初始化UIAppl ...
- 【BZOJ1251】序列终结者
Description 网上有许多题,就是给定一个序列,要你支持几种操作:A.B.C.D.一看另一道题,又是一个序列 要支持几种操作:D.C.B.A.尤其是我们这里的某人,出模拟试题,居然还出了一道这 ...