[大整数乘法] 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<n;i++){
A[i] = input[i];
}
for(int i = 0; i<n;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 < input.length; 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 < input.length; 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 < n - input.length; i++) {
ret[i] = '0';
}
for (int i = 0; i < input.length; 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 < input.length; i++) {
ret[i] = input[i];
}
for (int i = input.length; i < ret.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<lenMax;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] < newNum2[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] < newNum2[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表存储这些计算的结果,用到时直接查询结果,从而避免重复计算。
声明:代码是本人脑力劳动结果,请尊重他人劳动。转载注明出处!
[大整数乘法] java代码实现的更多相关文章
- 【老鸟学算法】大整数乘法——算法思想及java实现
算法课有这么一节,专门介绍分治法的,上机实验课就是要代码实现大整数乘法.想当年比较混,没做出来,颇感遗憾,今天就把这债还了吧! 大整数乘法,就是乘法的两个乘数比较大,最后结果超过了整型甚至长整型的最大 ...
- POJ 1001 解题报告 高精度大整数乘法模版
题目是POJ1001 Exponentiation 虽然是小数的幂 最终还是转化为大整数的乘法 这道题要考虑的边界情况比较多 做这道题的时候,我分析了 网上的两个解题报告,发现都有错误,说明OJ对于 ...
- OpenJudge 2980 大整数乘法
链接地址:http://bailian.openjudge.cn/practice/2980/ 题目: 总时间限制: 1000ms 内存限制: 65536kB 描述 求两个不超过200位的非负整数的积 ...
- 大整数乘法python3实现
因为python具有无限精度的int类型,所以用python实现大整数乘法是没意义的,可是思想是一样的.利用的规律是:第一个数的第i位和第二个数大第j位相乘,一定累加到结果的第i+j位上,这里是从0位 ...
- poj2389-Bull Math(大整数乘法)
一,题意: 大整数乘法模板题二,思路: 1,模拟乘法(注意"逢十进一") 2,倒序输出(注意首位0不输出) 三,步骤: 如:555 x 35 = 19425 5 5 5 5 5 ...
- 算法笔记_034:大整数乘法(Java)
目录 1 问题描述 2 解决方案 2.1 蛮力法 1 问题描述 计算两个大整数相乘的结果. 2 解决方案 2.1 蛮力法 package com.liuzhen.chapter5; import ...
- Java实现大整数乘法
1 问题描述 计算两个大整数相乘的结果. 2 解决方案 2.1 蛮力法 package com.liuzhen.chapter5; import java.math.BigInteger; publi ...
- Coefficient Computation (大整数、Java解决)
Coefficient Computation UVALive8265 题意:计算组合数C(n,k)的值并将值按给定的进制输出. 思路:Java大整数类硬上. PS:刚刚学完Java的大整数类,结果却 ...
- JS实现大整数乘法(性能优化、正负整数)
本方法的思路为: 一:检查了输入的合法性(非空,无非法字符) 二:检查输入是否可以进行简单计算(一个数为 0,1,+1,-1) 三:去掉输入最前面可能有的正负符号,并判断输出的正负 四:将输入的值分成 ...
随机推荐
- c++的vector容器
c++还有一个很常用的容器就是vector容器,他是数组实现的,是一种可变长的容器,在很多的时候可以简化我们的编程.可学习的链接:http://www.cnblogs.com/mr-wid/archi ...
- javascript实现数据结构:广义表
原文:javascript实现数据结构:广义表 广义表是线性表的推广.广泛用于人工智能的表处理语言Lisp,把广义表作为基本的数据结构. 广义表一般记作: LS = (a1, a2, ..., an ...
- HBase文件格式演变之路
Apache HBase是Hadoop的分布式开源的存储管理工具,很适合随机实时的io操作. 我们知道,Hadoop的Sequence File是一个顺序读写,批量处理的系统.可是为什么HBase能做 ...
- [CLR via C#]1.3 加载公共语言运行时
原文:[CLR via C#]1.3 加载公共语言运行时 1. 你生成的每个程序集可以是EXE,也可以是DLL.最终都是有CLR管理这些程序集中代码的执行. 2. VS2010中,创建新的EXE项目时 ...
- MSSQL Server 2008 数据库安装失败
1.Reporting Services目录临时数据库文件存在 出现这种问题的原因,是由于以前安装的SQL Server2008文件并没有卸载或删除干净造成 解决的办法如下: 找到 ...
- Linux中加入用户、删除用户时新手可能遇到的问题
Linux中加入用户.删除用户时新手可能遇到的问题 1.创建新用户后切换到新用户:No directory, logging in with HOME=/ 加入用户 #sudo us ...
- Objective-C的动态特性
最近几年中涌现了大量的Objective-C开发者.有些是从动态语言转过来的,比如Ruby或Python,有些是从强类型语言转过来的,如Java或C#,当然也有直接以Objective-C作为入门语言 ...
- hibernate的orphanRemoval
在@OneToMany与@OneToOne中使用orphanRemoval = true时候 改动保存时候setXXX org.springframework.orm.hibernate3.Hiber ...
- [顶]ORACLE PL/SQL编程详解之二:PL/SQL块结构和组成元素(为山九仞,岂一日之功)
原文:[顶]ORACLE PL/SQL编程详解之二:PL/SQL块结构和组成元素(为山九仞,岂一日之功) [顶]ORACLE PL/SQL编程详解之二: PL/SQL块结构和组成元素(为山九仞,岂一日 ...
- 推荐两个针对github的chrome插件
作为一只程序猿,在github上找代码.看代码是再正常不过的事情了.这时候有个工具可以方便你翻看代码,想必是极好的. Sourcegraph for GitHub 这个插件允许你像使用IDE那样浏览代 ...