大数字加法的实现(C)

C语言的内置类型int(32位系统下为4字节,32位),无符号整型最大可表示232-1=2147483647(字符长度为10位),而signed long long也最大为264-1=18446744073709551999(字符长度为20位),如果要计算更大的数的加法运算,计算机将无法存储这些数字,所以要转换为对字符串的处理。

可以使用小学学到的竖式计算的方式来处理,从个位开始逐位相加,和大于10则进位。

这里首先要考虑到字符串表示的大数在内存的存储方式,数字的位越高对应的数组的索引越小,即个位的数字字符在数组末尾。所以需要先将数字字符串逆序,然后将每一位使用字符对应的真实数值进行计算放入新的数组,最后将结果数组的每一个值还原为字符值并逆序输出。

解决思路

1. 先将相加的两个大数字符串num1[]和num2[]逆序处理

inline void swap(unsigned char * x, unsigned char * y)
{*x += *y;*y = *x - *y;*x = *x - *y;
}char * strReverse(char * str)
{char * start = str;char * end = str + strlen(str) - 1;while(start < end) swap((unsigned char *)start ++, (unsigned char *)end --); //对称交换头和尾return str;
}

这里swap是交换两个unsigned char类型变量的值,使用内联可以避免函数调用的栈开销,提高运行效率。

2. 每一位都转换为真实数值:c -= '0'

void transToRealVal(char * str, int len)
{char * start = str;char * end = str + len - 1;while(start <= end) {*start -= '0'; start ++;}return;
}

3. 从低到高逐位相加(注意进位)存入新的数组result[]

char * bignumPlus(char * num1, char * num2, int resultLen)
{strReverse(num1);strReverse(num2);transToRealVal(num1, strlen(num1));transToRealVal(num2, strlen(num2));char * result = malloc_type(char, resultLen);int resultSize = 0;int i = 0;for(i = 0; i < resultLen - 1; i ++){result[i] += (num1[i]+ num2[i]);resultSize = i + 1;if(result[i] >= 10) //向高位进位{result[i + 1]  += 1;result[i] %= 10;resultSize ++;}}transToCharVal(result, resultSize);strReverse(result);    return result;
}

4. 将result[]每一位都还原为数字对应的字符值:c += '0'

void transToCharVal(char * str, int len)
{char * start = str;char * end = str + len - 1;while(start <= end){*start += '0'; start ++;}return;
}

需要注意的是字符串参数str的每一位都是真实数值,中间某一个值可能为0,不能用strlen()取长度,必须传入参数len来确保str的真实长度。

5. 将result[]逆序处理

同1.

完整代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define Max(x,y) ((x) > (y) ? (x) : (y))
#define Min(x,y) ((x) < (y) ? (x) : (y))#define malloc_type(type, num) (type *)malloc(num * sizeof(type)) char * strdump(char * str, int size)
{char * string = (char *)malloc(size + 1);if(!string)return NULL;memset(string, '\0', size + 1);memcpy(string, str, Min(strlen(str), size));return string;
}void strfree(char ** str)
{if(*str){free(*str);*str = NULL;}
}inline void swap(unsigned char * x, unsigned char * y)
{*x += *y;*y = *x - *y;*x = *x - *y;
}char * strReverse(char * str, int len)
{char * start = str;char * end = str + Min(len, strlen(str)) - 1;while(start < end) swap((unsigned char *)start ++, (unsigned char *)end --);return str;
}void transToRealVal(char * str, int len)
{char * start = str;char * end = str + len - 1;while(start <= end) {*start -= '0'; //'RVal(*start);start ++;}return;
}void transToCharVal(char * str, int len)
{char * start = str;char * end = str + len - 1;while(start <= end){*start += '0'; //''CVal(*start);start ++;}return;
}char * bignumPlus(char * num1, char * num2, int resultLen)
{strReverse(num1);strReverse(num2);transToRealVal(num1, strlen(num1));transToRealVal(num2, strlen(num2));char * result = malloc_type(char, resultLen);int resultSize = 0;int i = 0;for(i = 0; i < resultLen - 1; i ++){result[i] += (num1[i]+ num2[i]);resultSize = i + 1;if(result[i] >= 10){result[i + 1]  += 1;result[i] %= 10;resultSize ++;}}transToCharVal(result, resultSize);strReverse(result);    return result;
}void destoryResult(char ** result)
{if(*result){free(*result);*result = NULL;}
}int main(int argc, char ** argv)
{int numLen1 = strlen(argv[1]);int numLen2 = strlen(argv[2]);int resultLen = Max(numLen1, numLen2) + 1; //此处+1考虑到最高位进位,计算结果的长度增加printf("resultLen=[%d]\n", resultLen);char * fmt = strdump("", 64); sprintf(fmt,"[%%%ds]\n", resultLen);//格式化输出,个位对齐char * num1 = strdump(argv[1], resultLen);printf(fmt, num1);char * num2 = strdump(argv[2], resultLen); printf(fmt, num2);//char * result = bignumPlus(num1, num2, resultLen);printf(fmt, result);//destoryResult(&result); //销毁结果strfree(&fmt);strfree(&num1);strfree(&num2);return 0;
}

运行结果

这里使用的linux环境,源码文件为bigNumPlus.c, 用gcc编译:

gcc -g -Wall -O3 -o bigNumPlus bigNumPlus.c

测试结果

两个数位数相同时

root@ubuntu:/home/ubuntu/Github# ./bigNumPlus 3 5
resultLen=[2]
[ 3]
[ 5]
[ 8]root@ubuntu:/home/ubuntu/Github# ./bigNumPlus 8 5
resultLen=[2]
[ 8]
[ 5]
[13]
root@ubuntu:/home/ubuntu/Github# ./bigNumPlus 1324515231423212344 8231472653421234213
resultLen=[20]
[ 1324515231423212344]
[ 8231472653421234213]
[ 9555987884844446557]root@ubuntu:/home/ubuntu/Github# ./bigNumPlus 29834728347283498678234092374 92340923947023947628346928348
resultLen=[30]
[ 29834728347283498678234092374]
[ 92340923947023947628346928348]
[122175652294307446306581020722]

两个数位数不相同时

root@ubuntu:/home/ubuntu/Github# ./bigNumPlus 29283742834238468273642039456234 9234092394702323423652345
resultLen=[33]
[ 29283742834238468273642039456234]
[        9234092394702323423652345]
[ 29283752068330862975965463108579]root@ubuntu:/home/ubuntu/Github# ./bigNumPlus 1234567893244523452345234584567523234598293465928364502374659029783452345456230345456 34534634567345672345623462345763456733453345634563456345754694057823465234567453645309237452093487528345023904
resultLen=[111]
[                          1234567893244523452345234584567523234598293465928364502374659029783452345456230345456]
[ 34534634567345672345623462345763456733453345634563456345754694057823465234567453645309237452093487528345023904]
[ 34534634567345672345623463580331349977976797979798040913277928656116931162931956019968267235545832984575369360]

总结

本文章简单地实现了大数字加法运算,有几个细节需要注意到,此外大数字的减法、乘法和除法可以参考加法的实现思路,对于带小数的大数字运算对小数部分可以单独处理,但是要参考浮点数的表示原理,与整数部分不一样。另外程序要尽可能的优化,减少不必要的操作和无意义的变量,对数组的操作要准确,防止越界。

大数字加法(C语言实现)相关推荐

  1. 大整数加法——C语言

    高精度计算--大整数加法 这是我写过的程序,主要也是为记录和学习,以下代码是该程序的思路和答案(注释是我自己写的),如有不对,请指出. 问题描述 求两个不超过200位的非负整数的和. 输入数据 有两行 ...

  2. NOI OJ 1.6 10:大整数加法 C语言

    描述 求两个不超过200位的非负整数的和. 输入 有两行,每行是一个不超过200位的非负整数,可能有多余的前导0. 输出 一行,即相加后的结果.结果里不能有多余的前导0,即如果结果是342,那么就不能 ...

  3. c语言怎么进行大整数加法,c语言 大整数加法

    2013-12-07 回答 以前我也做过一个大整数程序,2000!,不过那里面没有减法.做这个减法真让花时间啊. #include #include #include #define max 4000 ...

  4. Java快速入门到精通—大数字运算(BigDecimal 类)

    在Java中提供了用于大数字运算的类,即 java.math.BigInteger 类和 java.math.BigDecimal 类.这两个类用于高精度计算,其中BigInteger 类是针对整型大 ...

  5. 大整数加法(详细讲解C++)

    小白的自我成长之路 1. 整数运算 C语言的整数类型往往无法支持过大的数字加法计算. 在C++中实现大数据的运算,则需要借助其他方法(数据类型)实现.在实际操作当中使用数组或者vector容器进行储存 ...

  6. C++实现大整数加法

    大整数加法可谓是学习C++语言的一个里程碑.那么,如何在C++简单易懂地实现大整数加法呢? 概念思路 假定这两个十进制的大整数位数不超过255位. 那么,可以定义两个长度为255的字符数组(num1, ...

  7. 4、大数字运算(BigInteger类和BigDecimal类)

    在 Java 中提供了用于大数字运算的类,即 java.math.BigInteger 类和 java.math.BigDecimal 类.这两个类用于高精度计算,其中 BigInteger 类是针对 ...

  8. 剑指offer第12题打印从1到n位数以及大整数加法乘法

    字符和数字加减就是字符的ASCII码和数字直接加减. 方法一: 1)在字符串操作中给一个整形数字加(字符0)就是把它转化为字符,当然给一个字符减去(字符0)就可以把它转化为数字了:如果确实是最后一位字 ...

  9. java biginteger 运算_Java大数字运算之BigInteger 原创

    在 Java中,有许多数字处理的类,比如Integer 类.但是Integer 类有一定的局限性,下面我们就来看看比 Integer 类更厉害的一个,BigInteger类. BigInteger类型 ...

  10. 如何用C++来计算大数字乘法

     C++是比较高效地语言,用来做大鼠乘法效应一定没得说,那么如何用C++来计算大数字乘法,下面给出一个方法. 题解:用字符数组存两个因数,再将数组逆序以便处理,再对每一个数位进行处理,注意字符类型 ...

最新文章

  1. Python 写了一个网页版的「P图软件」,惊呆了!
  2. 基于深度学习的目标检测算法:SSD——常见的目标检测算法
  3. python2基础教程廖雪峰云-Python基础
  4. leetcode算法题--最长的斐波那契子序列的长度
  5. 【JVM】jstack和dump线程分析(2)
  6. struts2获取服务器临时目录
  7. 【原】Coursera—Andrew Ng机器学习—课程笔记 Lecture 12—Support Vector Machines 支持向量机...
  8. java-二分查找树的实现
  9. 建立学生选课表 mysql 语句_MySQL常用SQL语句(Python实现学生、课程、选课表增删改查)...
  10. C - Digital Path 计蒜客 - 42397 05-29
  11. MySQL数据库创建用户root@%
  12. python batch normalization_Batch Normalization 详解
  13. java jackson unicode_如何让Jackson JSON生成的数据包含的中文以unicode方式编码
  14. 【比原链】比原启动后去哪里连接别的节点
  15. oracle统计每个类别,Oracle统计分析函数集之一
  16. NGINX(二)内存池
  17. 嵌套的SQL另外一种写法
  18. 华为2台3928千兆电口对接trunk启不来
  19. 基于STM32移植UCGUI图形界面框架(3.9.0源码版本)
  20. 淘宝大数据产品解析之淘宝数据魔方技术架构(1)

热门文章

  1. 未援与用户在此计算机,在里番世界里拯救世界
  2. ERROR: pip‘s dependency resolver does not currently take into account all the packages that are ....
  3. 20个免费的SEO网站分析工具
  4. Python Requests爬取百思不得姐视频
  5. 酵素果冻在快手火了!三个品牌单品一周卖出5000万背后的秘密是什么?
  6. noip2018翻车记
  7. 记一次github 翻车事件
  8. 500 The server encountered an unexpected condition that prevented it from fulfilling the request.
  9. linux基础-命令
  10. Microsoft Word 教程:如何在 Word 中插入表格?