热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

[大整数乘法]java代码实现

本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。

上一篇写的“[大整数乘法]分治算法的时间复杂度研究”,这一篇是基于上一篇思想的代码实现,以下是该文章的连接:

http://www.cnblogs.com/McQueen1987/p/3348426.html

代码主要实现大整数乘法,过程中也涉及到[大整数加法] 和 [大整数减法] 的计算,代码如下:

 

类1

————————————————————————————————————————————————————————————

package bigIntNum;

public class NumDividEqual { public char[] A;
public char[] B;
int n;
/**
* 将数组均分为两份,分别存入数组A和数组B中;
* @param input
*/
public NumDividEqual(char[] input){
n = input.length/2;
A = new char[n];
B = new char[n];
for(int i = 0; i A[i] = input[i];
}
for(int i = 0; i B[i] = input[i + n];
}
}

public static void main(String[] args) {
// TODO Auto-generated method stub
}
}

  

类2

————————————————————————————————————————————————————————————

package bigIntNum;

import java.util.Arrays;

public class bigIntMult {
/**
* 将字符数组倒序排列
*
@param input
*
@return
*/
public char[] reverse(char[] input) {
char[] output = new char[input.length];
for (int i = 0; i ) {
output[i] = input[input.length - 1 - i];
}
return output;
}

/**
* 将大整数平均分成两部分
*
@param input
*
@return
*/
public NumDividEqual partition(char[] input) {
return new NumDividEqual(input);
}

/**
* 求两数组中较大数组的长度,如果其长度为奇数则+1变偶
*
@param num1
*
@param num2
*
@return
*/
public int calLength(char[] num1, char[] num2) {
int len = num1.length > num2.length ? num1.length : num2.length;
if (len == 1)
return 1;
len
+= len & 1;
return len;
}

/**
* 除去数字前面多余的0
*
@param input
*
@return
*/
public static char[] trimPrefix(char[] input) {
char[] ret = null;
for (int i = 0; i ) {
if (ret == null && input[i] == '0')
continue;
else {
if (ret == null) {
ret
= new char[input.length - i];//出去数字前面多余的0
}
ret[i
- (input.length - ret.length)] = input[i];
}
}
if (ret == null)
return new char[] { '0' };
return ret;
}

/**
* 数组如果长度不足n,则在数组前面补0,使长度为n。
*
@param input 输入数组要求数字的最高位存放在数组下标最小位置
*
@param n
*
@return
*/
public static char[] format(char[] input, int n) {//
if (input.length >= n) {
return input;
}
char[] ret = new char[n];
for (int i = 0; i ) {
ret[i] = '0';
}
for (int i = 0; i ) {
ret[n - input.length + i] = input[i];
}
return ret;
}

/**
* 大整数尾部补0。相当于移位,扩大倍数
*
@param input
*
@param n
*
@return
*/
public char[] addTail(char[] input, int n) {//
char[] ret = new char[input.length + n];
for (int i = 0; i ) {
ret[i] = input[i];
}
for (int i = input.length; i ) {
ret[i] = '0';
}
return ret;
}

/**
* 大整数加法
*
@param num1
*
@param num2
*
@return
*/
public char[] add(char[] num1, char[] num2) {
int len = num2.length > num1.length ? num2.length : num1.length;
int carry = 0;//进位标识
num1 = format(num1, len);
num2
= format(num2, len);
char[] ret = new char[len + 1];

for (int i = len - 1; i >= 0; i--) {
int tmp = num1[i] + num2[i] - 96;
tmp
+= carry;
if (tmp >= 10) {
carry
= 1;
tmp
= tmp - 10;
}
else {
carry
= 0;
}
ret[len
- i - 1] = (char) (tmp + 48);
}
ret[len]
= (char) (carry + 48);//最后一次,最高位的进位
return trimPrefix(reverse(ret));
}
/**
* 大整数减法:
*
@param num1 被减数,大整数乘法中只有一个减法(A+B)(C+D)-(AC+BD)=AC+BC>0,因此參數num1>num2且都为正
*
@param num2 减数
*
@return
*/
public static char[] sub(char[] num1, char[] num2) {
int lenMax = num1.length > num2.length ? num1.length : num2.length;
char[] newNum1 = Arrays.copyOf(format(num1, lenMax), lenMax);//字符串前面补0,使两串长度相同
char[] newNum2 = Arrays.copyOf(format(num2, lenMax), lenMax);

for(int i=0;i//when num1-num2<0 return
if((newNum1[i]=='0' && newNum1[i]=='0') || newNum1[i] == newNum2[i]){//newNum1 is bigger;
continue;
}
else if(newNum1[i] //不滿足參數num1>num2;
System.out.println("The Parameter in sub(A,B).A MUST Bigger Than B!");
System.exit(
0);
}
else break;
}

for(int i=lenMax-1;i>=0;i--){
if(newNum1[i] //result <0
newNum1[i] = (char) (newNum1[i] + '0' + 10 - newNum2[i]);
newNum1[i
-1] = (char) (newNum1[i-1] - 1);
}
else{
newNum1[i]
= (char) (newNum1[i] + '0' - newNum2[i]);
}
}
return trimPrefix(newNum1);
}
/**
* 大整数乘法
*
@param num1
*
@param num2
*
@return
*/
public char[] mult(char[] num1, char[] num2) {
char[] A, B, C, D, AC, BD, AjB, CjD, ACjBD, AjBcCjD, SUM;
int N = calLength(num1, num2);//求两数组中较大数组的长度,如果长度为奇数则+1变偶,方便二分成两部分
num1 = format(num1, N);//数组高位存整数的高位数;数字前面补0,使长度为n;
num2 = format(num2, N);
if (num1.length > 1) {
NumDividEqual nu1
= partition(num1);//将大整数平均分成两部分
NumDividEqual nu2 = partition(num2);
A
= nu1.A;
B
= nu1.B;
C
= nu2.A;
D
= nu2.B;
AC
= mult(A, C);//分治求大整数乘法
BD = mult(B, D);
AjB
= add(A,B);
CjD
= add(C,D);
ACjBD
= add(AC,BD);
AjBcCjD
= mult(AjB, CjD);

char[] tmp1 = addTail(sub(AjBcCjD, ACjBD), N / 2);//尾部补0,相当于移位
char[] tmp2 = add(addTail(AC, N), BD);
SUM
= add(tmp1, tmp2);
char[] test = trimPrefix(SUM);//除去结果前面多余的0
return test;
}
else {
Integer ret
= (num1[0] - 48) * (num2[0] - 48);
return ret.toString().toCharArray();
}
}

public static void main(String[] args) {
String st1
= "168746315641347979798";
String st2
= "164681654767446887797451316158";
char[] a = st1.toCharArray();
char[] b = st2.toCharArray();
bigIntMult bg
= new bigIntMult();
char[] ret = bg.mult(a, b);
System.out.println(ret);
}
}

 

 

代码优化:

1.可以写个hash表,存储一些常见的乘法,从而避免每次都重复计算。比如9999x9999999,里面有重复的9x9计算,可以考虑hash表存储这些计算的结果,用到时直接查询结果,从而避免重复计算。

 

声明:代码是本人脑力劳动结果,请尊重他人劳动。转载注明出处!

 

 


推荐阅读
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 3.223.28周学习总结中的贪心作业收获及困惑
    本文是对3.223.28周学习总结中的贪心作业进行总结,作者在解题过程中参考了他人的代码,但前提是要先理解题目并有解题思路。作者分享了自己在贪心作业中的收获,同时提到了一道让他困惑的题目,即input details部分引发的疑惑。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • Linux服务器密码过期策略、登录次数限制、私钥登录等配置方法
    本文介绍了在Linux服务器上进行密码过期策略、登录次数限制、私钥登录等配置的方法。通过修改配置文件中的参数,可以设置密码的有效期、最小间隔时间、最小长度,并在密码过期前进行提示。同时还介绍了如何进行公钥登录和修改默认账户用户名的操作。详细步骤和注意事项可参考本文内容。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • 本文介绍了游标的使用方法,并以一个水果供应商数据库为例进行了说明。首先创建了一个名为fruits的表,包含了水果的id、供应商id、名称和价格等字段。然后使用游标查询了水果的名称和价格,并将结果输出。最后对游标进行了关闭操作。通过本文可以了解到游标在数据库操作中的应用。 ... [详细]
  • 本文介绍了汉诺塔问题的迭代算法实现,通过递归的方式将盘子从一个地方搬到另一个地方,并打印出移动的顺序。详细介绍了算法的思路和步骤,以及示例代码的运行结果。 ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • 本文介绍了一个题目的解法,通过二分答案来解决问题,但困难在于如何进行检查。文章提供了一种逃逸方式,通过移动最慢的宿管来锁门时跑到更居中的位置,从而使所有合格的寝室都居中。文章还提到可以分开判断两边的情况,并使用前缀和的方式来求出在任意时刻能够到达宿管即将锁门的寝室的人数。最后,文章提到可以改成O(n)的直接枚举来解决问题。 ... [详细]
author-avatar
Larry_He
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有