首页 > 其他分享 >高精度加法(C语言实现)

高精度加法(C语言实现)

时间:2023-11-04 14:13:00浏览次数:30  
标签:高精度 int C语言 len2 len1 数组 加法 --

高精度加法(C语言实现)

介绍

众所周知,整数在C和C++中以intlonglong 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为换行符、空格或其他标识着数据输入结束的字符,则终止循环。

同时,循环中变化的数组下标我们直接记为len1len2,代表两个数字的长度。


显然,字符形式的数字并不好运算,所以,我们需要将每一位转换为整形存入数组,方便后续的计算。

那此时我们就会遇到一个问题,数组的第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,整形除法下取整,得到10,作为t的值,来参与下一位的运算。

最后,我们通过对最高位的01判断,来决定返回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的课程。

标签:高精度,int,C语言,len2,len1,数组,加法,--
From: https://www.cnblogs.com/coltea/p/17809261.html

相关文章

  • C语言小案例
    1.设计一个递归函数,计算Ackerman的值。Ackerman函数定义如下:       n+1                 m=0A(m,n)=A(m-1,1)             m≠0,n=0       A(m-1,A(m,n-1))        m≠0,n......
  • B站C语言第十课
    1,函数#include<stdio.h>#include<string.h>#include<stdlib.h>//intAdd(intx,inty){ intz=0; z=x+y; returnz;}intmain(){ inta=10; intb=20; intsum=Add(a,b); printf("%d\n",sum); return0;}2,牢记......
  • 贪心算法(C语言)
    一、会议安排问题1.1问题(1)对于每个会议i,起始时间bi和结束时间ei,且bi<ei(2)[bi,ei]与[bj,ej]不相交,则会议i和会议j相容,bi≥ej或bj≥ei(3)目标:在有限的时间内,尽可能多地安排会议1.2分析选择最早结束的会议1.3实现(1)初始化:按结束时间递增排序(2)选中第一......
  • C语言笔记3
    关键字1.C语言预先规定的,具有特定意义的字母组合(32个)。2.保留给语言本身使用,也称为保留字。标识符定义:为程序的构成成分命名。变量变量是程序执行期间其值可以改变的量,必须先定义后使用。变量定义本格式类型说明符变量名1变量名2...如inta,b,c;floatx;功能:指定......
  • 实验3—C语言函数应用编程
    1、实验任务1源代码1#include<stdio.h>2#include<stdlib.h>3#include<time.h>4#include<windows.h>5#defineN806voidprint_text(intline,intcol,chartext[]);//函数声明7voidprint_spaces(intn);//函数声明8voidprint_b......
  • C语言 循环队列
    什么是队列队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。什么是循环队列在实际使用队列时,为了使队列空间能重复使用,往往对......
  • C语言基础之基础的输入输出
    前言学一门编程语言,不能编写让用户输入数据然后输出处理后的数据的程序那么就等于没学,而在C语言中可以用printf()和scanf()函数进行输入和输出操作。这两个函数是内置的库函数,定义在stdio.h(头文件)中。printf()函数printf()函数用于输出操作。它将给定的语句打印到控制台......
  • C语言基础之第一个C程序
    前言在开始学习C语言的基础知识之前,我们需要学习如何编写、编译和运行第一个C程序。要编写第一个C程序,打开C控制台并编写以下代码,我这里直接使用vs2022进行代码的编写:#include<stdio.h>intmain(){ printf("Hello,World!"); return0;}运行效果如下:代码解......
  • C语言10进制转化为2进制
    #include<stdio.h>intmain(){ intx,i,flag=0x8000; scanf_s("%d",&x); for(i=0;i<16;i++){ if((flag&x)==0)printf("0"); elseprintf("1"); flag>>=1; } return0;}7,8,9行没怎么看懂,有......
  • C语言基础之理论概述
    C语言介绍C语言是一种高级程序设计语言,由贝尔实验室的DennisRitchie在1972年开发。C语言是结构化编程语言,支持变量、数据类型、运算符、表达式、流程控制语句和函数等基本程序设计元素。C语言广泛用于系统软件、应用程序、驱动程序和嵌入式系统开发等领域。C语言具有可移植性强......