JAVA实现高精度整数加减乘
首先,需要指出的是,java内的BigInteger类很好用,功能相当全面。像加减乘这样的基础操作都是可以胜任的。所以,在java中其实没有手动实现高精度的必要。
所以写下这篇博客的初衷并不是放在实际情况下使用,而是当做高精度算法的练习,也同时练习java编程能力。
封装类内容:
实现接口
克隆接口Cloneable,重写clone方法。便于复制
可比较接口Comparable,实现CompareTo方法,便于比较排序。
(可搭配各种数据结构使用)
成员变量
数组number,用于记录每一位,需要指出的是,该类仅支持十进制的运算。
数组长度len,用于表示数组中数字长度,便于统计和计算
符号变量sign,用于作为符号项参与运算。取值为1或-1.
成员方法:
构造方法
提供两种构造方法,用于初始化
传入整数,按位倒序转化进数组
传入字符串,检索符号,倒序存入数组
全局方法
打印方法void print,以带符号字符串的形式打印。
高精度加法void add,传入大整数,加到对象上
高精度减法void minus,传入大整数,计算减法
高精度乘法void multiply,传入大整数,计算乘法
克隆方法BigNumber clone,深克隆对象,返回克隆对象
比较方法int compareTo,与传入大整数进行比较,大1,小-1,相等0
私有方法
整理数组void sort,传入计算后的长度,计算符号并整理数组
代码
public class BigNumber implements Cloneable,Comparable<BigNumber> { short[] number = new short[50000]; int len = 0; int sign; BigNumber(int num) { if(num < 0) { num = -num; this.sign = -1; } else { this.sign = 1; } while(num != 0) { this.number[++len] = (short)(num % 10); num /= 10; } } BigNumber(String num) { this.len = num.length(); this.sign = 1; for(int i = this.len - 1;i > 0;i--) { number[this.len - i] = (short)(num.charAt(i) - '0'); } if(num.charAt(0) == '-') { this.len -= 1; this.sign = -1; } else { this.number[this.len] = (short)(num.charAt(0) - '0'); } } public BigNumber clone() { BigNumber num = null; try { num = (BigNumber) super.clone(); } catch (CloneNotSupportedException e) { // TODO Auto-generated catch block e.printStackTrace(); } num.number = number.clone(); return num; } public void print() { if(sign == -1) { System.out.print("-"); } for(int i = len;i >= 1;i--) { System.out.print(this.number[i]); } System.out.println(); } private void sort(int len) { while(this.number[len + 1] != 0) { len++; } if(this.number[len] < 0) { this.sign = -this.sign; for(int i = 1;i < len;i++) { if(this.number[i] == 0) { continue; } this.number[i] = (short)(10 - this.number[i]); this.number[i + 1]++; } this.number[len] *= -1; } while(len > 1 &&this.number[len] == 0) { len--; } this.len = len; } public void add(BigNumber num) { int len = Math.max(this.len, num.len); for(int i = 1;i <= len ;i++) { this.number[i] = (short)((this.number[i] * this.sign) + (num.number[i] * num.sign)); this.number[i + 1] += this.number[i] / 10; this.number[i] %= 10; if(this.number[i] < 0) { this.number[i + 1] --; this.number[i] += 10; } } sort(len); } public void minus(BigNumber num) { int len = Math.max(this.len, num.len); for(int i = 1;i <= len ;i++) { this.number[i] = (short)((this.number[i] * this.sign) - (num.number[i] * num.sign)); this.number[i + 1] += this.number[i] / 10; this.number[i] %= 10; if(this.number[i] < 0) { this.number[i + 1] --; this.number[i] += 10; } } sort(len); } public void multiply(BigNumber num) { BigNumber ans = new BigNumber(0); for(int i = 1;i <= this.len;i++) { for(int j = 1;j <= num.len;j++) { ans.number[i + j - 1] += (short)(this.number[i] * num.number[j] * this.sign * num.sign * ans.sign); ans.number[i + j] += ans.number[i + j - 1] / 10; ans.number[i + j - 1] %= 10; if(ans.number[i + j - 1] < 0) { ans.number[i + j]--; ans.number[i + j - 1] += 10; } } ans.sort(i + num.len); } number = ans.number.clone(); sign = ans.sign; len = ans.len; } @Override public int compareTo(BigNumber o) { o.minus(this); if(o.len == 0) { return 0; } return o.sign == 1 ? -1 : 1; } }
主要算法实现细节:
加法&减法
首先,为了处理负数的相加减。允许数组在计算时出现负数,并且边计算边整理的。
基本思路是尾对齐并按位直接相加减。由于在数组中数据逆序存放,所以尾对齐是默认设置。所以计算时仅需要从第一位开始至两者长度中较大者循环即可。
对每一位,取每一位的绝对值乘上该数符号作为真实值进行加减。算完后,进行整理,主要是进位和借位,保证每一位的值落在0-9上。
对于首位,允许出现负数,当首位为负数是,表示该数符号与当前符号相反,交于整理方法进行整理,传递数组长度为两者长度较长者。
整理方法
对计算完成的数进行整理,具体分为三步
第一步,从当前位开始找到最高位。方法就是从向后寻找第一个0.(当然这样的处理当当前位与最高位之间存在零的时候会出现bug,但其作为内部方法,通过在调用前对长度的准确把握,还是可以避开这个bug的。)
第二步,根据最高位整理数组并更新符号。 主要针对的,是当数组中的值为负的情况。由于在计算处理时,采用的是边算边进位。若出现负数,最终一定会出现一个负的最高位,其余位为正。当检测到最高位为负数时,翻转符号,最高位取相反数,从最低位至次高位开始翻转符号,并借位归正。例如 -1 2 9 符号为正, 整理后变为 7 1 ,符号为负。
第三步,从最高位起,计算真实长度。由于负数情况可能导致位数减少,该操作即为解决这种情况。实现方法为从最高位起,找到首个不为零的位。并处理答案为0的情况。并修正长度和符号成员变量。
乘法
乘法的高精度不能直接在原数组上进行,故定义答案变量ans。
模拟乘法竖式,每一次,取以为与另一因数相乘,取该位下标为偏移量,统计在答案数组中,并进行整理。
需要注意的是,在向答案数组中累加时,需要额外乘上答案变量的符号以确保符号统一。
- 点赞
- 收藏
- 分享
- 文章举报
- 关于高精度正整数计算的JAVA实现
- 最短路径--高精度整数(java实现)
- Java大整数实现计算catalan数
- 在Java程序中实现高精度打印-Java基础-Java-编程开发
- Java 实现大整数加减乘除
- java实现一个整数和一个小数的四则运算和求最大值,平均值。
- [Java] 自己实现字符串转换成整数
- 大整数类BIGN的设计与实现 C++高精度模板
- java中实现35选7的为随机,选出7个不重复的随机整数之hashmap去重
- java是实现的大整数运算!
- Java大数乘法的简单实现(整数和浮点数的乘法)
- 【老鸟学算法】大整数乘法——算法思想及java实现
- Java递归实现整数倒叙输出
- [密码学]ElGamal算法大整数版本的JAVA实现
- java实现无序整数数组组合得出最大数,如array={1,2,3},array2={123,132,213,231,312,321}。最大数是321
- JAVA实现数值的整数次方(《剑指offern》)
- java实现将整数转化为中文大写金额
- Java 用单链表实现多项式加减乘
- 实现大位整数的加/减/乘法的java工具类
- 实验一 分治与递归―整数划分 java实现