大整数的乘法

article/2025/9/14 4:47:16

大整数的乘法

(这里主要讨论的是两个较大的数相乘的效率问题,实际上并不是真正意义上的大数相乘。在java中有个BigInteger类已经可以储存大数,并提供了大数相乘的方法了。)

【分析】

       首先,当两个整数XY(位数分别为nm)进行相乘时,我们可以将这两个整数分别进行分割。

       假设 n == m 并且 2的幂,将n位的整数XY都分为2段,分别记为ABCD。这时每段长为 n / 2位。

       此时,X = A10^(n/2) + BY = C10^(n/2) + D

       那么XY = AC10^n + ((A - B)(D - C) + AC + BD)10^(n/2) + BD

       经过算法效率的分析,我们可以知道,T(n) = O(n^log3)

 

       这里我们要考虑几个问题:

问题1:当不等于 m时,我们如何使得两个整数的位数保持相等又不影响结果呢?

       我们可以将这两个整数以字符串的形式进行存储,当这两个整数的位数不相等时,我们可以在这两个整数调用算法进行相乘之前,再次初始化这两个字符串,在字符串的前面补加0,此时并不会影响到最终的结果。

 

问题2:当我们用字符串存储这两个整数的时候,又应该如何考虑整数的符号问题呢?当出现负整数的时候,我们将要考虑到如何截取整数的问题。

        我们可以创建一个BigNum类,用一个字符串类型存储这个整数的值,用一个int类型存储这个整数的符号。在创建对象的时候,如果字符串存储的是负整数,那么就应该将这个字符串截取出除符号外的部分来初始化这个对象的字符串属性,并且符号根据具体整数赋值101表示正整数,0表示负整数。

 

问题3:假如n不是2的幂,那我们应该怎么做呢?

       我们可以在初始化这两个字符串的同时,往字符串的前面补0,直到这两个字符串的长度为奇数为止。

 

       此外,根据上述所提出来的公式

XY = AC10^n + ((A - B)(D - C) + AC + BD)10^(n/2) + BD

采用分治法设计算法,定义一个multi(BigNum x, BigNum y)方法,那么有以下伪代码:

BigNum multi(BigNum x, BigNum y) {

       初始化xy的字符串属性(适当补0操作);

       分x的字符串为两段AB、分y的字符串为两段CD;

       根据ABCD创建相应的BigNum对象a, b, c, d;

       multi(a, c)计算AC的值;

       对AC进行后面补0的操作,相当于乘以10^n;

       multi(b, d)计算BD的值;

       return 计算AC10^n + ((A - B)(D - C) + AC + BD)10^(n/2) + BD的值;

}

【程序】

java语言编写程序,代码如下:

import java.util.Scanner;public class BigIntMul {public static void main(String[] args) {Scanner input = new Scanner(System.in);while(input.hasNext()) {String s1 = input.next();String s2 = input.next();BigNum b1 = new BigNum(s1);BigNum b2 = new BigNum(s2);BigNum r = multi(b1, b2);String s = r.n == 0 ? "-" : "";System.out.println(s + r.s);}}//定义大整数类static class BigNum {String s;int n;//存储大整数的正负号,1表示正,0表示负//定义BigNum对象,根据字符串的值,定义符号public BigNum(String s) {if(s.charAt(0) == '-') {n = 0;this.s = s.substring(1, s.length());}else {n = 1;this.s = s;}if(Long.parseLong(s) == 0)n = 1;}		//定义BigNum对象,符号自定义public BigNum(String s, int n) {if(s.charAt(0) == '-')this.s = s.substring(1, s.length());elsethis.s = s;this.n = n;if(Long.parseLong(s) == 0)n = 1;}public BigNum() {}public int len() {return s.length();}}//初始化两个BigNum对象,使得两个对象的值位数相等,且位数为偶数。不足的话前面为补0,并返回长度。//当两个数的长度相等,并且长度为1时,则直接返回长度值1public static int init(BigNum b1, BigNum b2) {int n;int len1 = b1.s.length();int len2 = b2.s.length();if(len1 > len2) {if(len1 % 2 != 0) {b1.s = "0" + b1.s;len1++;}n = len1;for(int i = 0; i < len1 - len2; i++)b2.s = "0" + b2.s;}else if(len1 < len2) {if(len2 % 2 != 0) {b2.s = "0" + b2.s;len2++;}n = len2;for(int i = 0; i < len2 - len1; i++)b1.s = "0" + b1.s;}else {if(len1 == 1)return 1;if(len1 % 2 != 0) {b1.s = "0" + b1.s;b2.s = "0" + b2.s;len1++;}n = len1;}return n;}public static BigNum multi(BigNum b1, BigNum b2) {int n = init(b1, b2);//当两个数的长度为1时,直接让这两个数相乘,返回BigNum对象。if(n == 1) {BigNum r = new BigNum();if((b1.n == 0 && b2.n == 1) || (b1.n == 1 && b2.n == 0))r.n = 0;elser.n = 1;long n1 = Long.parseLong(b1.s);long n2 = Long.parseLong(b2.s);r.s = (n1 * n2) + "";if(n1 == 0 || n2 == 0)r.n = 1;return r;}//将整数分为两个数,且不论这个整数是否为正数或负数,都将分解出来的数的符号定义为正号。//根据公式计算结果。BigNum a = new BigNum(b1.s.substring(0, n / 2), 1);BigNum b = new BigNum(b1.s.substring(n / 2, n), 1);BigNum c = new BigNum(b2.s.substring(0, n / 2), 1);BigNum d = new BigNum(b2.s.substring(n / 2, n), 1);BigNum ac = multi(a, c);BigNum bd = multi(b, d);long aa1 = /*a.n == 0 ? (-1) * Long.parseLong(a.s) : */Long.parseLong(a.s);long bb1 = /*b.n == 0 ? (-1) * Long.parseLong(b.s) : */Long.parseLong(b.s);long a_bl = aa1 - bb1;BigNum a_b = new BigNum(a_bl + "");long dd1 = /*d.n == 0 ? (-1) * Long.parseLong(d.s) : */Long.parseLong(d.s);long cc1 = /*c.n == 0 ? (-1) * Long.parseLong(c.s) : */Long.parseLong(c.s);long d_cl = dd1 - cc1;BigNum d_c = new BigNum(d_cl + "");BigNum abcd = multi(a_b, d_c);BigNum r1 = new BigNum(ac.s);for(int i = 0; i < n; i++) {r1.s = r1.s + "0";}long labcd = abcd.n == 0 ? (-1) * Long.parseLong(abcd.s) : Long.parseLong(abcd.s);long lac = ac.n == 0 ? (-1) * Long.parseLong(ac.s) : Long.parseLong(ac.s);long lbd = bd.n == 0 ? (-1) * Long.parseLong(bd.s) : Long.parseLong(bd.s);long lr2 = labcd + lac + lbd;BigNum r2 = new BigNum(lr2 + "");for(int i = 0; i < n / 2; i++)r2.s = r2.s + "0";long lr3 = lac * (long)(Math.pow(10, n)) + lr2 * (long)(Math.pow(10, n / 2)) + lbd;BigNum r3 = new BigNum(lr3 + "");if((b1.n == 0 && b2.n == 1) || (b1.n == 1 && b2.n == 0))r3.n = 0;elser3.n = 1;if(lr3 == 0)r3.n = 1;return r3;}
}

运行结果如下:



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

相关文章

实验一:大整数乘法

1.实验目的 掌握分治算法的基本思想、技巧和效率分析方法。熟练掌握用递归设计分治算法的基本步骤。学会利用分治算法解决实际问题。 2.实验内容 大整数乘法 采用分治算法实现两个n位二进制&#xff08;或者十进制&#xff09;大整数的乘法。 3.实验要求 根据实验内容构思…

分治法的经典问题——大整数相乘

分治法的原理 讨论问题时&#xff0c;先来了解一下什么是分治法。 分治法的意思就是&#xff0c;分而治之&#xff0c;也就是把一个问题&#xff0c;拆分成几个小问题&#xff0c;最后再汇总解决的方法 通过大整数相乘问题来了解分治法 假如现在我们要求两个大整数相乘的乘积…

大整数乘法(分治法)

大整数乘法&#xff08;分治法&#xff09; 题目描述&#xff1a;设X和Y都是n位的十进制整数&#xff0c;计算它们的乘积X*Y。 如果按照我们日常的计算方法&#xff0c;应该就是将两个数逐位相乘&#xff0c;最后加起来得到最终的结果&#xff0c;时间复杂度为O&#xff08;n2&…

大整数相乘算法

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

【大整数乘法】

问题 2.伪代码 理想情况下&#xff0c;XY位数相同 Mul(long long x,long long y,int num){Fh<--(x*y>0)?1:-1;x<--|x|; y<--|y|;if(num 0)then return 0;else if(num1) then return fh*x*y;else{x_high<--x/10^(num/2);x_low<--x mod 10^(num/2);y_high…

大整数乘法(大整数乘int型)

算法思想&#xff1a; 1.将大整数倒序储存到数组中&#xff08;方便进位&#xff09; 2.对同位相乘后的数取模10&#xff0c;推入结果数组中 3.对同位相乘后的数除以10&#xff0c;作为进位 5.去除可能出现的前导零 4.完成乘法后倒序输出 补充知识&#xff1a; 1、vector相关用…

C语言实现大整数乘法

转载自&#xff1a;点击打开链接 乘法规律&#xff0c;一个数的第i位和另一个数的第j位相乘&#xff0c;一定会累加到结果的第ij位&#xff0c;结果的数组一个数组元素存2位数&#xff0c;最后对结果处理进位&#xff0c;最后打印出来 方法一见上面链接https://www.cnblogs.c…

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

一、分析 整数的数值超过计算机硬件所能表示的最大值时&#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账号在…