高精度加法(C语言实现)
高精度加法(C语言实现)
介绍
众所周知,整数在C和C++中以int ,long,long long三种不同大小的数据存储,数据大小最大可达2^64,但是在实际使用中,我们仍不可避免的会遇到爆long long的超大数运算,这个时候,就需要我们使用高精度算法,来实现巨大数的运算。
高精度的本质是将数字以字符串的形式读入,然后将每一位分别存放入int数组中,通过模拟每一位的运算过程,来实现最终的运算效果。
今天,我们先讲解高精度加法的C语言实现:
声明
但其实我这版C语言的高精度算法封装是很有问题的,没有stl,字符串的操作是比较繁琐的,以后熟悉C++后我会再写一版简易的,标准的高精度算法解析,但通过本文了解高精度的思路也是没有问题的。
代码实现
#include<stdio.h>
const int N = 100001;
int add(int a[], int b[], int c[], int len1, int len2)
{
int t = 0, i = 0, max = len1 > len2 ? len1 : len2;
//max指两加数中较大者的位数,两数之和c位数至少是max
//标识变量t值为0或1,代表是否进位,初始为0
for (; i <= max; i++)//运算到较大者位数后一位停止
{
c[i] = (a[i] + b[i] +t) % 10;//c的每一位为两数该位之和加上t再模去10
t = (a[i] + b[i] + t) / 10;//若和>10,则c[i]取其个位,t取其十位
}//i遍历至max+1
if (c[i - 1] == 1) return i;//若最高位为1,则返回c长度为max+1,即i
else return i - 1;//否则返回max,即i-1
}
int main()
{
char str1[N], str2[N];//两个数的字符串形式
int a[N] = { 0 }, b[N] = { 0 }, c[N] = { 0 };//ab为加数,c为和
char x;
int len1 = 0, len2 = 0;//两数位数
do {
scanf("%c", &x);
str1[len1++] = x;
}while (x != '\n');
do{
scanf("%c", &x);
str2[len2++] = x;
} while (x != '\n');
len1--; len2--;//将数据读入str1和str2,同时记录位数
for (int i = len1 - 1; i >= 0; i--)
a[i] = str1[len1 - i - 1]-'0';
for (int i = len2 - 1; i >= 0; i--)
b[i] = str2[len2 - i - 1] - '0';//将ab的每一位转换为整形存入数组
int len3 = add(a, b, c, len1, len2);//执行高精度加法函数
for (int i = len3 - 1; i >= 0; i--)
printf("%d", c[i]);//输出
return 0;
}
思路分析
对大数来说,输入便已经是一个有些麻烦的问题,无法读取整形,只能以字符串形式,而且连有几位数字都不知道。
char str1[N], str2[N];//两个数的字符串形式
int a[N] = { 0 }, b[N] = { 0 }, c[N] = { 0 };//ab为加数,c为和
char x;
int len1 = 0, len2 = 0;//两数位数
do {
scanf("%c", &x);
str1[len1++] = x;
}while (x != '\n');
do{
scanf("%c", &x);
str2[len2++] = x;
} while (x != '\n');
len1--; len2--;//将数据读入str1和str2,同时记录位数
这里是主函数的变量声明和输入部分,若是程序只运行一次高精度运算,我们可以把变量的声明放在主函数以外,来能减少函数的参数个数。
我们将读取的字符赋值给x,然后再放入字符串数组,最后对x进行判断,若x为换行符、空格或其他标识着数据输入结束的字符,则终止循环。
同时,循环中变化的数组下标我们直接记为len1和len2,代表两个数字的长度。
显然,字符形式的数字并不好运算,所以,我们需要将每一位转换为整形存入数组,方便后续的计算。
那此时我们就会遇到一个问题,数组的第0位应该存放最高位还是存放个位呢?先看代码实现:
for (int i = len1 - 1; i >= 0; i--)
a[i] = str1[len1 - i - 1]-'0';
for (int i = len2 - 1; i >= 0; i--)
b[i] = str2[len2 - i - 1] - '0';//将ab的每一位转换为整形存入数组
在这段函数中,我们从高位向低位,将每一位的字符-'0',得到他的整形,然后存入数组,最终得到从低位到高位的新数组。
为什么要反过来存放呢,这就要考虑到一个最高位进位的问题。
数组后面存放最高位,在最高位进位时显然比最高位放在第0位操作起来更方便,前者只需要在下一位+1,而后者想要进位,可能只能依靠于额外的标记变量了。
这种问题在后面的高精度乘法中更是明显,所以,在高精度运算中,为了使高位灵活变动,我们一般都采用倒序的存放顺序,即数组前面存低位,后面存高位。
到这里,我们就将准备工作做完了,数字已经放入数组,长度也已得知,这时我们就需要写一个函数来运行高精度加法,代码如下:
int add(int a[], int b[], int c[], int len1, int len2)
{
int t = 0, i = 0, max = len1 > len2 ? len1 : len2;
//max指两加数中较大者的位数,两数之和c位数至少是max
//标识变量t值为0或1,代表是否进位,初始为0
for (; i <= max; i++)//运算到较大者位数后一位停止
{
c[i] = (a[i] + b[i] +t) % 10;//c的每一位为两数该位之和加上t再模去10
t = (a[i] + b[i] + t) / 10;//若和>10,则c[i]取其个位,t取其十位
}//i遍历至max+1
if (c[i - 1] == 1) return i;//若最高位为1,则返回c长度为max+1,即i
else return i - 1;//否则返回max,即i-1
}
虽然图中解析已经非常到位了,但我还是简单讲解一下吧。
首先从i=0位开始,将a[i]与b[i]和t相加,其个位便是c在该位的值,所以我们对他模上10,其大于10时需要进位,那我们就将其除以10,整形除法下取整,得到1或0,作为t的值,来参与下一位的运算。
最后,我们通过对最高位的0或1判断,来决定返回max还是max+1。
这时,我们已经将结果存入c了,只差输出了,但想要输出我们怎么知道c有几位呢?最高位到底有没有进位呢?那其实我们的函数返回值就是c的长度了。
int len3 = add(a, b, c, len1, len2);//执行高精度加法函数
for (int i = len3 - 1; i >= 0; i--)
printf("%d", c[i]);//输出
这样,我们从后往前一位位输出,就得出了最终结果了。
总结
总而言之言而总之,高精度算法就是单独将每一位数字存入数组,分别计算,模拟我们手动计算的过程,接下来的减法和乘法除法的核心思想都是这个,那么以上便是对高精度加法算法的介绍,本文由凉茶coltea撰写,思路来自AcWing,大佬yxc的课程。
高精度加法(C语言实现)的更多相关文章
- SCAU1143 多少个Fibonacci数--大菲波数【杭电-HDOJ-1715】--高精度加法--Fibonacci数---大数比较
/*******对读者说(哈哈如果有人看的话23333)哈哈大杰是华农的19级软件工程新手,才疏学浅但是秉着校科联的那句“主动才会有故事”还是大胆的做了一下建一个卑微博客的尝试,想法自己之后学到东西都 ...
- NEFU 2016省赛演练一 F题 (高精度加法)
Function1 Problem:F Time Limit:1000ms Memory Limit:65535K Description You know that huicpc0838 has b ...
- java算法 蓝桥杯 高精度加法
问题描述 在C/C++语言中,整型所能表示的范围一般为-231到231(大约21亿),即使long long型,一般也只能表示到-263到263.要想计算更加规模的数,就要用软件来扩展了,比如用数组或 ...
- 用c++实现高精度加法
c++实习高精度加法 最近遇到一个c++实现高精度加法的问题,高精度问题往往十复杂但发现其中的规律后发现并没有那么复杂,这里我实现了一个整数的高精度加法,主要需要注意以下几点: 1:将所需输入的数据以 ...
- 高精度加法——经典题 洛谷p1601
题目背景 无 题目描述 高精度加法,x相当于a+b problem,[b][color=red]不用考虑负数[/color][/b] 输入输出格式 输入格式: 分两行输入a,b<=10^500 ...
- 高精度加法--C++
高精度加法--C++ 仿照竖式加法,在第一步计算的时候将进位保留,第一步计算完再处理进位.(见代码注释) 和乘法是类似的. #include <iostream> #include < ...
- hdu1002 A + B Problem II(高精度加法) 2016-05-19 12:00 106人阅读 评论(0) 收藏
A + B Problem II Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
- POJ 3181 Dollar Dayz(全然背包+简单高精度加法)
POJ 3181 Dollar Dayz(全然背包+简单高精度加法) id=3181">http://poj.org/problem?id=3181 题意: 给你K种硬币,每种硬币各自 ...
- leetcode 67. Add Binary (高精度加法)
Given two binary strings, return their sum (also a binary string). For example,a = "11"b = ...
- leetcode 66. Plus One(高精度加法)
Given a non-negative number represented as an array of digits, plus one to the number. The digits ar ...
随机推荐
- Centos7安装Python3.x
一.修改yum源 查看Centos发行版本 cat /etc/redhat-release 换阿里云yum源 备份原始yum源 mv /etc/yum.repos.d/CentOS-Base.repo ...
- Unity UGUI的PhysicsRaycaster (物理射线检测)组件的介绍及使用
Unity UGUI的PhysicsRaycaster (物理射线检测)组件的介绍及使用 1. 什么是PhysicsRaycaster组件? PhysicsRaycaster是Unity UGUI中的 ...
- Python和PyTorch深入实现线性回归模型:一篇文章全面掌握基础机器学习技术
1. 简介 1.1 线性回归模型概述 线性回归是一种统计学中的预测分析,该方法用于建立两种或两种以上变量间的关系模型.线性回归使用最佳的拟合直线(也称为回归线)在独立(输入)变量和因变量(输出)之间建 ...
- 压缩CSS样式与js样式
方法一: 使用插件:JS & CSS Minifier (Minify) 使用方法: 效果: 或者按下F1,输入命令:Minify:Document
- CF1601 题解
偶然看这一场的题目,忽然很有感觉,于是写了一下 A 题面 考虑每一位可以单独分开考虑 考虑单独的一位,每次要选 \(m\) 个位置,可能产生贡献的位置就是这位为 1 的数,设数量为 \(x\),则 \ ...
- Mybatis开发中的常用Maven配置
Mybatis导入Maven配置 <!-- MyBatis导入 --> <dependency> <groupId>org.mybatis</groupId& ...
- CF-1860C Game on Permutation题解
题意:在一条数轴上,Alice可以跳到在你所在点前面且值比当前所在点小的点.每回合可以向任意符合要求的点跳一次.当轮到Alice的回合同时不存在符合要求的点,Alice就赢了.Alice可以选择一个点 ...
- AI绘画Stable Diffusion实战操作: 62个咒语调教-时尚杂志封面
今天来给大家分享,如何用sd简单的咒语输出好看的图片的教程,今天做的是时尚杂志专题,话不多说直入主题. 还不会StableDiffusion的基本操作,推荐看看这篇保姆级教程: AI绘画:Stable ...
- RocketMQ系列(一) 基本介绍
RocketMQ系列(一) 基本介绍 1.MQ 作用 MQ 的应用场景主要包含以下 3 个方面: 1.1.异步与解耦 当我们下了一个订单之后,订单服务会进行 RPC 同步调用 支付服务.库存服务.物流 ...
- Linux 主机磁盘繁忙度监控实战shell脚本
Linux 磁盘繁忙度是指磁盘的使用率和活动水平.可以通过一些工具来监测磁盘繁忙度,如 iostat.iotop.sar 等. 其中,iostat 是一个常用的工具,可以提供关于磁盘活动的详细统计信息 ...