C语言实现大整数乘法

article/2025/9/14 5:28:22

转载自:点击打开链接

乘法规律,一个数的第i位和另一个数的第j位相乘,一定会累加到结果的第i+j位,结果的数组一个数组元素存2位数,最后对结果处理进位,最后打印出来

方法一见上面链接https://www.cnblogs.com/king-ding/p/bigIntegerMul.html

方法二

void IntMultiply(int a[], int b[], int c[], int ma, int nb) {int i, j;memset(c, 0, (ma + nb)*sizeof(c[0]));for(i = 0; i < ma; ++i) {for(j = 0; j < nb; ++j) {c[i + j + 1] = c[i + j + 1] + a[i] * b[j];//printf("%d ",c[i + j + 1]);}//printf("\n");}for(i = ma + nb - 1; i > 0 ; --i) {if(c[i] > 9) {c[i - 1] = c[i - 1] + c[i] / 10;c[i] = c[i] % 10;}}
}

思路:

简单来说,方法二就是先不算任何的进位,也就是说,将每一位相乘,相加的结果保存到同一个位置,到最后才计算进位。

例如:result[200]用来保存结果,计算98×21,步骤如下


由上面可以看出,result的数据为result[100] = {0, 18, 27, 9}

接下来就处理进位,注意看,巧妙的地方来了:

有result末尾到首位计算:

第一次:result[3] = 9; result[2] = 27;

A.先将result[3]除个位以外的数加给前一位,也就是result[2]:result[2] = result[2]+result[3]/10 = 27 + [9/10]=27; 注:数学里面的[]为取整符。如[0.9] = 0

B.然后把result[3]的个位保存到result[3]:

>> result[3] = result[3]%10 = 9;

第二次,向前一位,result[2] = 27, result[1] = 18;

重复第一次的A、B步骤,求得result[1] = result[1]+result[2] / 10=18+[27/10] = 20;

>> result[2] = result[2] % 10 = 7

第三次,再向前一位,result[1] = 20, result[0] = 0

重复之前的步骤,

>> result[0] = result[0]+result[1]/10=0+[20]/10=2

>> result[1] = result[1] % 10 = 0;

至此,已经算到首位,result此时的结果为:result[100] = {2, 0, 7, 9}可以知道这就是结果:99×21=2079;

核心代码:

先是不进位的各位之和:

for(j = 0; j < num2Len; j++)
{for(i = 0; i < num1Len; i++){/* result第一位是用来保存result长度的,而第二位是保存结果最后的进位的* 没有进位,则result[1]为0,所以每位相乘之和是从第三位(即result[2])* 开始。这里是本程序的比较巧妙的地方,需要仔细想想。* */result[i+j+2] += Int(num1[i]) * Int(num2[j]);}
}
接下来是处理进位的代码:
/* 这个循环用来处理进位的,所以要从result的最后一位一直处理到首位。* 要注意result的总长度是resultLen+1,有一位是保存result的长度,而* C语言下标是从0开始,所以result的最后一位的下标就是resultLen,而* 第一位就是1。*/
for(i = resultLen; i > 1; i--)
{result[i-1] += result[i]/10;result[i] = result[i]%10;
}

注意:这个方法有一个大坑,就是保存结果的result的数据类型必须至少是int,而不能是char,为什么呢?先想想再打开答案。

#include<stdio.h>
#include<string.h>
#include<malloc.h>#define and &&           /**************/
#define or ||            /* python风格 */
#define not !            /*            */
#define Int(X) (X - '0') /**************/int *multiBigInteger(const char *, const char *);
int checkNum(const char *);int main(void)
{char num1[100] = {'\0'}, num2[100] = {'\0'};printf("Please input two nunber(less than 100 digits):\n> ");while(scanf("%s%s", num1, num2) != EOF){int *result = NULL;int i, change = 0;//对输入的数据进行检验if(strlen(num1) > 100 or strlen(num2) > 100){printf("per number must less than 100 digits\n");return 1;}if(checkNum(num1) or checkNum(num2)){printf("ERROR: input must be an Integer\n");return 1;}printf("num1:\t%s\nnum2:\t%s\n", num1, num2);result = multiBigInteger(num1, num2);/* 输出结果result,result[0]保存着result的长度,* 所以下标要从1开始 */printf("result:\t");for(i = 1; i <= result[0]; i++){if(result[i] != 0) //这一步用来去掉前导0,第一位为0跳过不输出change = 1;if(not change){if(i > 1)        //这一步用来判断结果是否为0,{                //如果结果第二位还是0,就判断为0printf("0");break;}continue;}printf("%d", result[i]);}printf("\n");printf("\nPlease input two nunber(less than 100 digits):\n> ");}return 0;
} //用于检测输入的是否是数字,如果是就返回0,不是就返回1
int checkNum(const char *num)
{int i;for(i = 0; (size_t)i < strlen(num); i++){if(num[i] < '0' or num[i] > '9'){return 1;}}return 0;
}//返回结果result,为一片内存块,类似数组
int *multiBigInteger(const char *num1, const char *num2)
{int *result = NULL;                //用来保存最终结果int num1Len = strlen(num1);        //num1的长度int num2Len = strlen(num2);        //num2的长度int resultLen;                     //结果的最大长度int i, j;                          //循环计数器resultLen = num1Len + num2Len;     //结果长度最大为num1长度和num2长度之和//初始化result为0result = (int *)malloc((resultLen+1)*sizeof(int));memset(result, 0, (resultLen+1)*sizeof(int));result[0] = resultLen; //result的第一位是用来保存result的长度的。/* num1乘以num2,由于这里采用先不进位的算法,所以算法是按从左到右* 按顺序来乘,然后将每位的结果保存到result的每一位中,循环一次* reult就从下一位开始求和。如下:(左边为正常算法,右边为本程序算法)**     54321     |     54321*    ×  123     |    ×  123*    -------    |   --------*    162963     |     54321*   108642      |     108642*   54321       |      162963*   --------    |   ---------*   6681483     |     6681483** */for(j = 0; j < num2Len; j++){for(i = 0; i < num1Len; i++){/* result第一位是用来保存result长度的,而第二位是保存结果最后的进位的* 没有进位,则result[1]为0,所以每位相乘之和是从第三位(即result[2])* 开始。这里是本程序的比较巧妙的地方,需要仔细想想。* */result[i+j+2] += Int(num1[i]) * Int(num2[j]);}}/* 这个循环用来处理进位的,所以要从result的最后一位一直处理到首位。* 要注意result的总长度是resultLen+1,有一位是保存result的长度,而* C语言下标是从0开始,所以result的最后一位的下标就是resultLen,而* 第一位就是1。*/for(i = resultLen; i > 1; i--){result[i-1] += result[i]/10;result[i] = result[i]%10;}printf("num1Len:%d\nnum2Len:%d\n", num1Len, num2Len);return result;
}大整数相乘2完整代码

程序运行结果:


总结:

这是一道非常经典而且必须要掌握的题目,所以看到这篇文章的你最好能认真理解一下。



http://chatgpt.dhexx.cn/article/GM8VnbpS.shtml

相关文章

大整数乘法(简单模拟乘法过程)

一、分析 整数的数值超过计算机硬件所能表示的最大值时&#xff0c;那么我们只能借助软件的方法来实现大整数的乘法了。 我们可以使用字符串来模拟大整数的乘法&#xff0c;算法的思想就是使用我们在小学时学过的乘法&#xff0c;一位位相乘&#xff0c;最后计算出结果。如下&…

算法总结——大整数乘法

问题描述 求两个不超过200位的非负整数的积。 输入数据 有两行&#xff0c;每行是一个不超过200位的非负整数&#xff0c;没有多余的前导0。 输出要求 一行&#xff0c;即相乘后的结果。结果里不能有多余的前导0&#xff0c;即如果结果是342&#xff0c;那么就不能输出为0342。…

大整数的乘法(分治法)

通常执行一次加法或乘法运算所需的计算时间看作一个仅取决于计算机硬件处理速度的常数。这个仅在参加运算的整数能在计算机硬件对整数的表示范围内直接处理才是合理的。若要精确地表示大整数并在计算结果中要求精确得到所有位数上的数字&#xff0c;就必须用软件的方法来实现大…

分治法-大整数乘法

问题分析&#xff1a; 在计算机上处理一些大数据相乘时&#xff0c;由于计算机硬件的限制&#xff0c;不能直接进行相乘得到想要的结果。可以将一个大的整数乘法分而治之&#xff0c;将大问题变成小问题&#xff0c;变成简单的小数乘法再进行合并&#xff0c;从而解决上述问题…

大整数乘法

设计一个有效的算法&#xff0c;可以计算两个n位大整数的乘法运算。 如果按照我们日常的计算方法&#xff0c;应该就是将两个数逐位相乘&#xff0c;最后加起来得到最终的结果。由于是大整数乘法&#xff0c;那么我们用string来存储这两个数&#xff0c;因为是要做乘法&#x…

大整数乘法算法

一 转换为二进制求&#xff0c;推导出的公式适合十进制计算 设X和Y都是n位的二进制整数&#xff0c;现在要计算它们的乘积XY。我们可以用小学所学的方法来设计一个计算乘积XY的算法&#xff0c;但是这样做计算步骤太多&#xff0c;显得效率较低。如果将每2个1位数的乘法或加法看…

大整数乘法的详解

一.问题 由于编程语言提供的基本数值数据类型表示的数值范围有限&#xff0c;不能满足较大规模的高精度数值计算&#xff0c;因此需要利用其他方法实现高精度数值的计算&#xff0c;于是产生了大数运算。尤其是乘法运算&#xff0c;下面就是大整数的乘法的过程&#xff08;加 …

Ubuntu server树莓派版本默认用户名密码及密码修改

树莓派安装的Ubuntu server镜像&#xff0c; 默认的初始用户及密码&#xff1a; ubuntu # user ubuntu # passwd默认信息查看 在烧入镜像的内存卡中&#xff0c; 可以查看到默认的用户信息 默认密码修改 在登录界面 输入初始化的用户名和密码后&#xff0c; 会提示是第一…

2022.04.04树莓派最新镜像问题,树莓派如何设置初始化的账户和密码

树莓派最新的arm64位系统&#xff0c;更新时间是2022年4月4日&#xff0c;这个版本的树莓派取消了默认的账户密码&#xff0c;也就是原来一直使用的pi和对应的默认密码raspberry被取消了&#xff0c;现在如果想要使用的话必须自己设置&#xff0c;下面有两种方法可以设置自己的…

树莓派启用无密码 sudo

启用无密码 sudo&#xff0c;可以在不提供密码的情况下在树莓派上运行程序。 登录 Raspberry Pi 命令行界面。假设 Raspberry Pi 的默认用户名和密码分别为 pi 和 raspberry。在命令行界面中&#xff0c;键入以下命令&#xff1a; sudo nano /etc/sudoers 3. 通过添加以下行启…

最新树莓派系统PUTTY用默认用户名和密码登录不上的解决方法

最近我在树莓派配置深度学习环境&#xff0c;然后直接载了别的博主的树莓派镜像&#xff0c;发现博主给的用户名&#xff0c;密码登不上&#xff0c;于是乎&#xff0c;就打算自己配置深度学习环境&#xff0c;结果我下在了最新版本的树莓派镜像系统&#xff08;2022-04-04-ras…

树莓派默认账号密码串口登录不了的Bug解决

一、问题总结 我用的树莓派型号是树莓派Pi3,刷机用的镜像是2023版的&#xff0c;23版的镜像文件较大8G的SD卡不够用 问题描述&#xff1a;刷完机在用串口登录树莓派的时候登录不了 &#xff01;&#xff01;&#xff01; 默认账号&#xff1a;pi 默认密码&#xff1a;raspb…

树莓派raspberry pi 4 SSH默认密码无法登录解决办法

以前玩过一段时间树莓派&#xff0c;只要开通ssh就可以&#xff0c;默认用户pi,默认密码: raspberry。 远程连接就可以。 但今天再玩却死活无法登录&#xff0c;如下&#xff1a; 出了什么幺蛾子哦&#xff1f;&#xff01;&#xff01; 上网一查&#xff0c;才知道pi账号在…

【入坑树莓派】烧录系统都烧录了三次(树莓派默认账户密码错误/已删除)

为什么会烧录了三次&#xff1f;我因为实在不知道问题出在哪&#xff0c;所以只能推倒重来三次。。。 三次&#xff0c;两次连接不上WiFi&#xff0c;好不容易一次连接上了&#xff0c;出现了下面这幅画面 再三确认了默认用户名是pi&#xff0c;密码raspberry&#xff0c;奈何…

树莓派用默认账号和密码登录不上怎么办;修改树莓派的密码

目录 一、重置树莓派的默认账号和密码 二、修改树莓派的密码 三、超级用户和普通用户的切换 一、重置树莓派的默认账号和密码 在SD卡中根目录建立文件userconf 在userconf中输入如下内容&#xff1a; pi:$6$/4.VdYgDm7RJ0qM1$FwXCeQgDKkqrOU3RIRuDSKpauAbBvP11msq9X58c8Q…

树莓派默认密码_树莓派介绍:没有显示器,怎样远程控制树莓派?

树莓派(Raspberry Pi)是学习计算机知识、架设服务器的好工具&#xff0c;价格低廉&#xff0c;可玩性高。 由于树莓派系统开始时默认是不开启ssh连接的&#xff0c;没有开启ssh就无法连接电脑&#xff0c;后续的操作也就无从谈起。 准备工作 1.烧录好系统的树莓派3B主板 2.普…

树莓派默认密码_树莓派快速指南,从购买到开机

本文给树莓派初学者&#xff0c;或者准备入手树莓派的同学看&#xff0c;主要包括什么是树莓派&#xff0c;入门树莓派需要那些配件&#xff0c;如何烧录树莓派系统&#xff0c;和树莓派的开机指南。如果你不知道学习树莓派需要那些配件&#xff0c;或者购买了树莓派不知道怎么…

树莓派的登录

一、串口登录&#xff1a; 由于树莓派在默认情况下&#xff0c;树莓派的串口和蓝牙链接。而我们要进行串口登录就得断开蓝牙&#xff0c;把串口用来进行数据通信。 1.打开SD卡根目录的"config.txt"文件&#xff0c;将以下内容添加在最后并且保存。 dtoverlaypi3-m…

树梅派raspberrypi的su密码root密码是什么

入手了树梅派4B,上电后&#xff0c;安装portainer的时候想获得root权限&#xff0c;输入su&#xff0c;恩&#xff1f;密码是多少&#xff1f;不记得了&#xff0c;输了好几遍登录密码也不对&#xff0c;无法进入了。 查了一下&#xff0c;原来树莓派的Raspbian系统root用户默…

【mysql】mysql 模糊查询 like 语句

mysql 模糊查询 like 语句 一 like 语句 %xxx%&#xff1a;查询 username 字段中包含 xxx 的记录。 select * from user where username like ‘%xxx%’; %xxx&#xff1a;查询 username 字段中以 xxx 结尾的记录。 select * from user where username like ‘%xxx’; xx…