大数的四则运算(加法、减法、乘法、除法)

大数的四则运算(加法、减法、乘法、除法)

前言:

    在计算机中数字表示的范围是有限制的,比如我们熟知的 int、float、double 等数据类型所能表示的范围都是有限的,如果我们要对位数达到几十位、几百位、上千位的大整数进行计算,这些数据类型显然不能满足我们的要求,因此我们需要通过算法来实现这些功能。

 

1、大数加法

    两个大数我们可以用数组来保存,然后在数组中逐位进行相加,再判断该位相加后是否需要进位,为了方便计算,我们将数字的低位放在数组的前面,高位放在后面。

下面是两个正的大整数相加算法的C语言参考代码:

复制代码
 1 #include<stdio.h>2 #include<string.h>3 4 #define MAX 1000    // 大数的最大位数 5 6  7 /*8   大数加法 9   参数: 
10   num1为第一个大数,用字符数组保存
11   num2为第二个大数
12   sum数组保存相加的结果  即:num1+num2=sum
13   返回值:返回数组sum的有效长度,即计算结果的位数 
14  */
15 int Addition(char num1[], char num2[], int sum[])
16 {
17     int i, j, len;
18     int n2[MAX] = {0};
19     int len1 = strlen (num1); // 计算数组num1的长度,即大数的位数 
20     int len2 = strlen (num2); // 计算数组num2的长度,即大数的位数 
21 
22     len = len1>len2 ? len1 : len2; // 获取较大的位数
23     //将num1字符数组的数字字符转换为整型数字,且逆向保存在整型数组sum中,即低位在前,高位在后
24     for (i = len1-1, j = 0; i >= 0; i--, j++) 
25         sum[j] = num1[i] - '0';
26     // 转换第二个数 
27     for (i = len2-1, j = 0; i >= 0; i--, j++)
28         n2[j] = num2[i] - '0';
29     // 将两个大数相加 
30     for (i = 0; i <= len; i++)
31     {
32         sum[i] += n2[i];  // 两个数从低位开始相加 
33         if (sum[i] > 9)   // 判断是否有进位 
34         {   // 进位 
35             sum[i] -= 10;
36             sum[i+1]++;
37         }
38     }
39     if(sum[len] != 0)  // 判断最高位是否有进位 
40         len++;
41     return len;   // 返回和的位数 
42 }
43 
44 int main()
45 {
46     int i, len;
47     int sum[MAX] = {0}; // 存放计算的结果,低位在前,高位在后,即sum[0]是低位 
48     char num1[] = "1234567891234567891234"; // 第一个大数 
49     char num2[] = "2345678912345678913345"; // 第二个大数 
50     len = Addition(num1, num2, sum);    // 两数相加 
51     printf("%s\n  +\n%s\n  =\n", num1, num2);
52     // 反向输出求和结果
53     for (i = len-1; i >= 0; i--)
54         printf("%d", sum[i]);
55     printf("\n"); 
56     return 0;
57 }
复制代码

 

2、大数减法

    相减算法也是从低位开始减的。先要判断被减数和减数哪一个位数长,若被减数位数长是正常的减法;若减数位数长,则用被减数减去减数,最后还要加上负号;当两数位数长度相等时,最好比较哪一个数字大,否则负号处理会很繁琐;处理每一项时要,如果前一位相减有借位,就先减去上一位的借位,无则不减,再去判断是否能够减开被减数,如果减不开,就要借位后再去减,同时置借位为1,否则置借位为0。

下面是C语言参考代码:

复制代码
  1 #include<stdio.h>2 #include<string.h>3 4 #define MAX 1000    // 大数的最大位数 5 6  7 /*8   大数减法 9   参数: 10   num1为被减数,用字符数组保存11   num2为减数 12   sum数组保存相减的结果   即:num1-num2=sum13   返回值:返回数组sum的有效长度,即计算结果的位数 14  */15 int Subtraction(char num1[], char num2[], int sum[])16 {17     int i, j, len, blag;18     char *temp;19     int n2[MAX] = {0};20     int len1 = strlen(num1); // 计算数组num1的长度,即大数的位数 21     int len2 = strlen(num2); // 计算数组num2的长度,即大数的位数22     23     // 在进行减法之前要进行一些预处理 24     blag = 0; // 为0表示结果是正整数,为1表示结果是负整数 25     if(len1 < len2) // 如果被减数位数小于减数26     {27         blag = 1; // 标记结果为负数28         // 交换两个数,便于计算 29         temp = num1;30         num1 = num2;31         num2 = temp;32         len = len1;33         len1 = len2;34         len2 = len;35     }36     else if(len1 ==len2) // 如果被减数的位数等于减数的位数37     {  38         // 判断哪个数大 39         for(i = 0; i < len1; i++)40         {41             if(num1[i] == num2[i])42                 continue;43             if(num1[i] > num2[i])44             {45                 blag = 0; // 标记结果为正数 46                 break;47             } 48             else49             {50                 blag = 1; // 标记结果为负数 51                 // 交换两个数,便于计算 52                 temp = num1;53                 num1 = num2;54                 num2 = temp;55                 break;56             } 57         } 58     }59     len = len1>len2 ? len1 : len2; // 获取较大的位数60     //将num1字符数组的数字转换为整型数且逆向保存在整型数组sum中,即低位在前,高位在后61     for (i = len1-1, j = 0; i >= 0; i--, j++) 62         sum[j] = num1[i] - '0';63     // 转换第二个数 64     for (i = len2-1, j = 0; i >= 0; i--, j++)65         n2[j] = num2[i] - '0';66     // 将两个大数相减 67     for (i = 0; i <= len; i++)68     {69         sum[i] = sum[i] - n2[i]; // 两个数从低位开始相减 70         if (sum[i] < 0)   // 判断是否有借位 71         {    // 借位 72             sum[i] += 10;73             sum[i+1]--;74         }75     }76     // 计算结果长度 77     for (i = len1-1; i>=0 && sum[i] == 0; i--)78         ;79     len = i+1;80     if(blag==1)81     {82         sum[len] = -1;  // 在高位添加一个-1表示负数 83         len++;84     }85     return len;   // 返回结果的位数 86 }87 88 int main()89 {90     int i, len;91     int sum[MAX] = {0}; // 存放计算的结果,低位在前,高位在后,即sum[0]是低位 92     char num1[] = "987654321987654321"; // 第一个大数 93     char num2[] = "123456789123456789"; // 第二个大数 94     len = Subtraction(num1, num2, sum);    // 两数相减 95     // 输出结果96     printf("%s\n  -\n%s\n  =\n", num1, num2);97     if(sum[i=len-1] < 0) // 根据高位是否是-1判断是否是负数98     {99         printf("-"); // 输出负号
100         i--;
101     }
102     for (; i >= 0; i--)
103         printf("%d", sum[i]);
104     printf("\n"); 
105     return 0;
106 } 
复制代码

 

3、大数乘法

    首先说一下乘法计算的算法,从低位向高位乘,在竖式计算中,我们是将乘数第一位与被乘数的每一位相乘,记录结果,之后,用第二位相乘,记录结果并且左移一位,以此类推,直到计算完最后一位,再将各项结果相加,得出最后结果。

    计算的过程基本上和小学生列竖式做乘法相同。为了编程方便,并不急于处理进位,而是将进位问题留待最后统一处理。

    总结一个规律: 即一个数的第i 位和另一个数的第j 位相乘所得的数,一定是要累加到结果的第i+j 位上。这里i, j 都是从右往左,从0 开始数。
    ans[i+j] = a[i]*b[j];

    另外注意进位时要处理,当前的值加上进位的值再看本位数字是否又有进位;前导清零。

下面是C语言的两个正大数相乘的参考代码:

复制代码
 1 #include<stdio.h>2 #include<string.h>3 4 #define MAX 1000    // 大数的最大位数 5 6  7 /*8   大数乘法 9   参数: 
10   num1为第一个因数,用字符数组保存
11   num2为第二个因数
12   sum数组保存相乘的结果  即:num1*num2=sum
13   返回值:返回数组sum的有效长度,即计算结果的位数 
14  */
15 int Multiplication(char num1[],char num2[], int sum[])
16 {
17     int i, j, len, len1, len2;
18     int a[MAX+10] = {0};
19     int b[MAX+10] = {0};
20     int c[MAX*2+10] = {0};
21     
22     len1 = strlen(num1);
23     for(j = 0, i = len1-1; i >= 0; i--) //把数字字符转换为整型数 
24         a[j++] = num1[i]-'0';
25     len2 = strlen(num2);
26     for(j = 0, i = len2-1; i >= 0; i--)
27         b[j++] = num2[i]-'0';
28     
29     for(i = 0; i < len2; i++)//用第二个数乘以第一个数,每次一位 
30     {
31         for(j = 0; j < len1; j++)
32         {
33             c[i+j] += b[i] * a[j]; //先乘起来,后面统一进位
34         }
35     }
36     
37     for(i=0; i<MAX*2; i++) //循环统一处理进位问题
38     {
39         if(c[i]>=10)
40         {
41             c[i+1]+=c[i]/10;
42             c[i]%=10;
43         }
44     }
45 
46     for(i = MAX*2; c[i]==0 && i>=0; i--); //跳过高位的0
47     len = i+1; // 记录结果的长度 
48     for(; i>=0; i--)
49         sum[i]=c[i];
50     return len; 
51 }
52 
53 int main()
54 {
55     int i, len;
56     int sum[MAX*2+10] = {0}; // 存放计算的结果,低位在前,高位在后,即sum[0]是低位 
57     char num1[] = "123456789123456789"; // 第一个大数 
58     char num2[] = "123456789123456789"; // 第二个大数 
59     len = Multiplication(num1, num2, sum);
60     // 输出结果
61     printf("%s\n  *\n%s\n  =\n", num1, num2);
62     for(i = len-1; i>=0; i--)
63         printf("%d", sum[i]); 
64     printf("\n"); 
65     return 0;
66 } 
复制代码

 

4、大数除法

    大数除法是四则运算里面最难的一种。不同于一般的模拟,除法操作不是模仿手工除法,而是利用减法操作来实现的。其基本思想是反复做除法,看从被除数里面最多能减去多少个除数,商就是多少。逐个减显然太慢,要判断一次最多能减少多少个整数(除数)的10的n次方。

以7546除以23为例:

    先用7546减去23的100倍,即减去2300,可以减3次,余下646,此时商就是300 (300=100*3);

    然后646减去23的10倍,即减去230,可以减2次,余下186,此时商就是320 (320=300+10*2);

    然后186减去23,可以减8次,余下2,此时商就是328 (328=320+1*8);

    因为2除以23的结果小于1,而我们又不用计算小数点位,所以不必再继续算下去了。

下面是C语言的两个正大数相除的参考代码,计算结果中没有小数:

复制代码
  1 #include<stdio.h>2 #include<string.h> 3 #define MAX 1000    // 大数的最大位数 4 5 // 注: 6 // 本代码在以下博客代码中进行修改: 7 // http://www.cnblogs.com/javawebsoa/archive/2013/08/01/3231078.html8 // 9 10 11 /*12   函数SubStract功能:13   用长度为len1的大整数p1减去长度为len2的大整数p214   结果存在p1中,返回值代表结果的长度15   不够减:返回-1 , 正好够:返回016 */ 17 int SubStract(int *p1, int len1, int *p2, int len2)18 {19     int i;20     if(len1 < len2)21         return -1;22     if(len1 == len2 )23     {                        // 判断p1 > p224         for(i = len1-1; i >= 0; i--)25         {26             if(p1[i] > p2[i])   // 若大,则满足条件,可做减法27                 break;28             else if(p1[i] < p2[i]) // 否则返回-129                 return -1;30         }31     }32     for(i = 0; i <= len1-1; i++)  // 从低位开始做减法33     {34         p1[i] -= p2[i];         // 相减 35         if(p1[i] < 0)           // 若是否需要借位36         {   // 借位 37             p1[i] += 10;38             p1[i+1]--;39         }40     }41     for(i = len1-1; i >= 0; i--)  // 查找结果的最高位42     {43         if( p1[i] )             //最高位第一个不为044             return (i+1);       //得到位数并返回45     } 46     return 0;                   //两数相等的时候返回047 }48 49 50 /*51   大数除法---结果不包括小数点 52   num1 被除数53   num2 除数 54   sum  商,存放计算的结果,即:num1/num2=sum55   返回数组sum的有效长度,即商的位数 56 */ 57 int Division(char num1[], char num2[], char sum[])58 {59     int k, i, j;60     int len1, len2, len=0;     //大数位数61     int dValue;                //两大数相差位数62     int nTemp;                 //Subtract函数返回值63     int num_a[MAX] = {0};      //被除数64     int num_b[MAX] = {0};      //除数65     int num_c[MAX] = {0};      //商 66 67     len1 = strlen(num1);       //获得大数的位数68     len2 = strlen(num2);69     70     //将数字字符转换成整型数,且翻转保存在整型数组中 71     for( j = 0, i = len1-1; i >= 0; j++, i-- )72         num_a[j] = num1[i] - '0';73     for( j = 0, i = len2-1; i >= 0; j++, i-- )74         num_b[j] = num2[i] - '0';75 76     if( len1 < len2 )          //如果被除数小于除数,直接返回-1,表示结果为077     {78         return -1;79     }80     dValue = len1 - len2;      //相差位数81     for (i = len1-1; i >= 0; i--)    //将除数扩大,使得除数和被除数位数相等82     {83         if (i >= dValue)84             num_b[i] = num_b[i-dValue];85         else                         //低位置086             num_b[i] = 0;87     }88     len2 = len1;89     for(j = 0; j <= dValue; j++ )    //重复调用,同时记录减成功的次数,即为商90     {91         while((nTemp = SubStract(num_a, len1, num_b+j, len2-j)) >= 0)92         {93             len1 = nTemp;            //结果长度94             num_c[dValue-j]++;       //每成功减一次,将商的相应位加195         }96     }97     // 计算商的位数,并将商放在sum字符数组中 98     for(i = MAX-1; num_c[i] == 0 && i >= 0; i-- );  //跳过高位0,获取商的位数 99     if(i >= 0)
100         len = i + 1; // 保存位数 
101     for(j = 0; i >= 0; i--, j++)     // 将结果复制到sum数组中 
102         sum[j] = num_c[i] + '0';
103     sum[j] = '\0';   // sum字符数组结尾置0 
104     return len;      // 返回商的位数 
105 } 
106 
107 
108 int main()
109 {
110     int i;
111     int len;                // 商的位数
112     char num1[MAX] = "1234567899876543210";   // 第一个大数
113     char num2[MAX] = "20160415123025";              // 第二个大数
114     char sum[MAX] = {0};    // 计算结果 
115 
116     //scanf("%s", num1);      //以字符串形式读入大数
117     //scanf("%s", num2);
118     
119     len = Division(num1, num2, sum); 
120     
121     //输出结果
122     printf("%s\n  ÷\n%s\n  =\n", num1, num2);
123     if( len>=0 )
124     {
125         for(i = 0; i < len; i++ )
126             printf("%c", sum[i]);
127     }
128     else
129     {
130         printf("0");
131     }
132     printf("\n");
133     
134     return 0;
135 }
复制代码

 

5、使用Java提供的类

    在Java中提供了BigInteger类和BigDecimal类,分别用来处理大整数和大浮点数,我们只要调用里面提供的方法就能很方便的进行大数的四则运算,具体实现可参考:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/445396.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

随机过程1

随机过程1概述1.参考书目2.主要内容3.概率论--基本概念回顾3.1对“不确定性”的认识3.2 应对“不确定性”应该怎么做3.3随机变量&#xff08;Random Variable&#xff09;3.4分布函数&#xff08;Distribution Function&#xff09;3.5概率密度&#xff08;Density&#xff09;…

数组基操三连(4)

题目一 给定一个长度为N的整型数组arr&#xff0c;其中有N个互不相等的自然数1~N 请实现arr的排序 但是不要把下标0~N-1位置上的数值通过直接赋值的方式替换成1~N。 要求&#xff1a;时间复杂度为O(N)&#xff0c;额外空间复杂度为O(1)。 思路&#xff1a;从左向右检查&…

Linux(1)-touch,mkdir,rm,mv,cp,ls,cd,cat

Linux1-实用终端命令1. touch, mkdir2. rm, mv, cp3. ls(通配符),cd(绝对/相对路径)4. cat, more/less文件内容浏览文件/目录-增删查改, 文件内容查看.1. touch, mkdir touch新文件 &#xff1a;在当前文件夹下&#xff0c;创建文件。文件不存在则创建新文件&#xff1b;文件存…

数组精选题目三连(5)

子数组的最大累加和问题 输入一个整形数组&#xff0c;求数组中连续的子数组使其和最大。比如&#xff0c;数组x 应该返回 x[2..6]的和187. 这四个代码完成的功能都是求最大子数组&#xff08;注意用词准确&#xff0c;子数组连续&#xff0c;子序列可以不连续&#xff09;。…

大数据学习(1)-大数据概述

文章目录目录大数据产生背景大数据概念大数据影响大数据应用大数据关键技术大数据产业大数据&#xff0c;云计算&#xff0c;物联网关系云计算物联网大数据&#xff0c;物联网&#xff0c;云计算三者之间联系目录 大数据产生背景 三次信息化浪潮 根据IBM前首席执行官郭士纳福…

redis——事件

redis服务器是一个事件驱动程序。 需要处理两类事件&#xff1a; 1&#xff09;文件事件&#xff1a;redis是通过套接字与客户端或者其他服务器连接的&#xff0c;而文件事件就是服务器对套接字操作的抽象。 2&#xff09;时间事件&#xff1a;服务器对一些定时操作的抽象。…

redis——客户端

redis服务器是典型的一对多服务器&#xff0c;通过使用由IO多路复用技术实现的文件事件处理器&#xff0c;redis服务器使用了单线程单进程的方式来处理请求。 客户端的属性 描述符 客户端状态的 fd 属性记录了客户端正在使用的套接字描述符&#xff1a; typedef struct red…

大数据学习(2-1)-Hadoop安装教程-单机模式和伪分布模式(Ubuntu14.04LTS)

文章目录目录1.linxu的安装1.1安装Linux虚拟机1.2安装Linux和Windows双系统2.Hadoop的安装2.1 Hadoop安装前配置2.1.1 配置Hadoop用户2.1.2 安装 ssh , 配置ssh免密登录2.1.3 安装java环境2.2 Hadoop的安装3.Hadoop单机版配置4.Hadoop伪分布版配置目录 1.linxu的安装 1.1安装…

mysql——JDBC

概述 JDBC&#xff1a;java Data Base Connectivity ,java数据库连接&#xff0c;它是一种用于执行sql语句的java API&#xff0c;为多种关系数据库提供统一访问。 其实就是一组用java编写的类和接口。 JDBC API 提供两类主要接口&#xff1a; 1&#xff09;面向开发人员的…

servlet基础总结

什么是servlet Servlet&#xff08;Server Applet&#xff09;是Java Servlet的简称&#xff0c;是小服务程序或服务连接器&#xff0c;是用Java编写的服务器端程序&#xff0c;主要功能在于交互式地浏览和修改数据&#xff0c;生成动态Web内容. 狭义的Servlet是指Java语言实…

大数据学习(3)- 分布式文件系统HDFS

文章目录目录1.分布式文件系统1.1 计算机集群概念1.2 分布式文件系统结构2.HDFS简介2.1 HDFS设计的目标2.2HDFS的局限性2.3 块的概念2.4 HDFS主要组件及其功能2.4.1 名称节点2.4.2 第二名称节点2.4.3 数据节点3.HDFS体系结构3.1 HDFS体系结构介绍3.2 HDFS体系结构的局限性4.HDF…

大数据学习(4)--分布式数据库HBase

文章目录目录1.HBase概述1.1BigTable1.2 HBase简介1.3 HBase和传统的关系型数据库之间的区别2.HBase访问接口3.HBase数据模型3.1 数据模型概述3.2 数据模型相关概念3.3 数据坐标3.4 概念视图3.5 物理视图3.6 面向列的存储4.HBase的实现原理4.1 HBase功能组件4.2 表和region4.3 …

servlet中的数据存储

在servlet基础中&#xff0c;我们&#xff1a; 用以下几种方式实现数据存储和共享&#xff1a; 1&#xff09;在客户端页面和服务器端程序之间&#xff0c;用request中的getParameter()方法共享数据 2&#xff09;在请求和请求之间&#xff0c;可以用get/setAttribute方法来共…

Linux(2)-tar,find,grep,xargs

常用命令1. 打包压缩/解包解压缩 tar1.1 打包 tar -czvf xxx.tar.gz xxx1.2 解压 tar -xzvf xxx.tar.gz2.文件/目录搜索2.1 find文件/目录查找2.2 grep文本匹配3. 复合命令3.1 > 重定向3.2 | 管道.shutdown1. 打包压缩/解包解压缩 tar tar和gzip是对黄金搭档&#xff1a;ta…

servlet——三兄弟的另外两个:过滤器/监听器

过滤器 我们写多了servlet会发现&#xff0c;很多代码和功能是重复的&#xff0c;比如&#xff1a;解决中文乱码问题、权限验证、日志的记录等&#xff0c;他们的特点是&#xff1a;代码相同或相似、分散在不同位置、不利于维护。 过滤器就是他们的解决办法。 过滤器是请求到…

kaggle(05)---Event Recommendation Engine Challenge(基础版)

文章目录目录1.比赛相关介绍1.1 比赛介绍1.2 数据集介绍1.3 评价标准介绍1.4 个人理解2. 解决方案2.1 统计用户和event信息2.2 计算用户相似度2.3 用户社交关系信息处理2.4 构建event和event相似度数据2.5 活跃度/event热度数据2.6 构建特征2.7 模型构建和预测3. 遇到的问题4. …