要求:
实现十进制长正整数的四则运算(加、减、乘、整除),并进行测试;
输入两个字符串形式的运算数,计算运算结果。要求对输入合法性进行检验,对于长正整数,输入不能为’0’-‘9’以外的字符;如非法输入返回false;
实现思路
先构造出长整数数据类型BIgInteger以及相关的构造函数以及四则运算函数,对于数据类型的实现有以下两种方法:
1.可以使用Java的math包里的BigInteger数据类型直接实现,十分方便 http://blog.csdn.net/qfikh/article/details/52832196。
2.不使用math包自己实现。根据自己的需要相当于仿照着math包里的BigInteger实现,直接查看源码包含其他运算很繁杂,所以在网上找到了简易的BigInteger的三则运算加减乘,然后自己就简单的补充了除法。很多都借鉴了链接的内容,里面的三则运算很详细易懂http://blog.csdn.net/piaopiao8786/article/details/7785492
其中由于输入字符串的合法性,则对于合法的字符如000012需要在构造函数中将前面的0去除,因此稍微修改了构造函数public BigInteger(String numberStr) 代码如下:
//字符串构造函数
public BigInteger(String numberStr) {
if(numberStr.charAt(0) == '-'){ //判断正负
sign = false;
StringBuilder sb = new StringBuilder(numberStr);
sb.deleteCharAt(0);
numberStr = new String(sb);
}else{
sign = true;
}
int count = 0;
for(int i = 0; i<numberStr.length(); i++){//字符串有效数字前有多少个0
if(numberStr.charAt(i) == '0'&&i != numberStr.length()-1) count++;
}
digits = new byte[numberStr.length()-count];
for(int i = 0;i < numberStr.length()-count;i++){
switch(numberStr.charAt(i+count)){
case '0': digits[i] = 0;break;
case '1': digits[i] = 1;break;
case '2': digits[i] = 2;break;
case '3': digits[i] = 3;break;
case '4': digits[i] = 4;break;
case '5': digits[i] = 5;break;
case '6': digits[i] = 6;break;
case '7': digits[i] = 7;break;
case '8': digits[i] = 8;break;
case '9': digits[i] = 9;break;
}
}
}
除法思路:除法是在加减乘的基础上实现的,很普通的除法,由于是正整数,因此没有除以0的问题。 先判断除数与被除数位数,比较复杂的是被除数位数大于除数,我的实现是移位相减,恢复余数法。位数相等时候需要判断是否相同数值。
//接着上面链接的三则运算
//长正整数整除法(默认为正整数即不会出现除以0)
public BigInteger divide(BigInteger another) {
BigInteger res = new BigInteger();
int length1 = this.digits.length;
int length2 = another.digits.length;
//位数不相等length1<length2 则为默认值0
if(length1<length2){}
//位数相等
else if(length1==length2){
int num = 0;//用于位数相等结果
boolean isAbsoluteEqual = true;//两数是否相同
for(int i = 0; i < this.digits.length; i++){
if(this.digits[i] != another.digits[i]){
isAbsoluteEqual = false;
break;
}
}
if(isAbsoluteEqual) num = 1;
else{//不相同进行减法
BigInteger temp = new BigInteger();
temp = this;
while(temp.sign==true){
temp = temp.subtract(another);
num++;
}
num--;//结果为负数减一
}
res.digits[0] = (byte)num;
}
//位数this>another
else{
BigInteger that = new BigInteger();//this的复制
that = this;
int count = length1-length2;
int[] result = new int[count+1];
for(int i=0; i<=count; i++){//count位的循环计算
BigInteger temp = new BigInteger();
temp.digits = new byte[length1-i];
for(int j=0; j<length2; j++){ //给temp赋值
temp.digits[j] = another.digits[j];
}
//减法过程
int number = 0;//存储一轮减法结果
while(that.sign==true){
that = that.subtract(temp);
number++;
}
number--;
that = that.add(temp);
result[i] = number;
}
//消去前面的0
int zeroCount = 0;
for(int i = 0;i < result.length;i++){
if(result[i] == 0){
zeroCount++;
}else{
break;
}
}
res.digits = new byte[result.length - zeroCount];
for(int i = 0;i < res.digits.length;i++){
res.digits[i] = (byte)result[zeroCount + i];
}
}
return res;
}
public BigInteger divide(int num) {
return this.divide(new BigInteger(num));
}
实现了数据类型及相关的函数,接下来就是实现相关题目要求,即对输入的字符串的合法性进行检验,在进行四则运算,所以重新写了类Compute里面调用之前写的数据类型BigInteger来实现长正整数四则运算,代码如下:
//import java.math.BigInteger;math包里自带的BigInteger
//直接使用自己编写在同一个包里的BigInteger
public class Compute {
//检验字符串
public static boolean Check(String s){
int num = 0;
for(int i = 0; i<s.length(); i++){
//检查是否存在非法字符
if(s.charAt(i)-'0' < 0 || s.charAt(i)-'0' > 9){
return false;
}
//检查是否为正整数
if(s.charAt(i)=='0'){
num++;
}
}
if(num == s.length()) return false;
else return true;
}
//加法
public static String Add(String s1, String s2){
if(Check(s1)&&Check(s2)){
BigInteger n1 = new BigInteger(s1);
BigInteger n2 = new BigInteger(s2);
String ret = n1.add(n2).toString();
return ret;
}
else return String.valueOf(false);
}
//减法
public static String Subtract(String s1, String s2){
if(Check(s1)&&Check(s2)){
BigInteger n1 = new BigInteger(s1);
BigInteger n2 = new BigInteger(s2);
String ret = n1.subtract(n2).toString();
return ret;
}
else return String.valueOf(false);
}
//乘法
public static String Multiply(String s1, String s2){
if(Check(s1)&&Check(s2)){
BigInteger n1 = new BigInteger(s1);
BigInteger n2 = new BigInteger(s2);
String ret = n1.multiply(n2).toString();
return ret;
}
else return String.valueOf(false);
}
//除法
public static String Divide(String s1, String s2){
if(Check(s1)&&Check(s2)){
BigInteger n1 = new BigInteger(s1);
BigInteger n2 = new BigInteger(s2);
String ret = n1.divide(n2).toString();
return ret;
}
else return String.valueOf(false);
}
public static void main(String args[])
{
String s1 = new String("10000000000000000000000000000");
String s2 = new String("100000000000000123");
String s3 = Compute.Divide(s1, s2);
System.out.println(s3);
}
}
测试的话可以使用Junit 实用的教程http://blog.csdn.net/shenpibaipao/article/details/78590749和http://blog.csdn.net/andycpp/article/details/1327147/
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.After;
import org.junit.Test;
import org.junit.Ignore;
public class ComputeTest {
@Before
public void before() throws Exception {
}
@After
public void after() throws Exception {
System.out.println();
}
@Test
public void testAdd() throws Exception {
System.out.println("开始测试加法");
String[] a = new String[]{"a88888","6549876541649875487989121364"};
String[] b = new String[]{"888888","9854225774125485623215"};
String[] c = new String[]{"false","6549886395875649613474744579"};
for(int i = 0; i<a.length; i++){
assertEquals(c[i],Compute.Add(a[i], b[i]));
System.out.println(a[i]+" + "+b[i]+"\n预期结果:"+c[i]+"\n运行结果:"+Compute.Add(a[i], b[i]));
}
}
@Test
public void testSubtract() {
System.out.println("开始测试减法");
String[] a = new String[]{"a88888","6549876541649875487989121364"};
String[] b = new String[]{"888888","9854225774125485623215"};
String[] c = new String[]{"false","6549866687424101362503498149"};
for(int i = 0; i<a.length; i++) {
assertEquals(c[i],Compute.Subtract(a[i], b[i]));
System.out.println(a[i]+" - "+b[i]+"\n预期结果:"+c[i]+"\n运行结果:"+Compute.Subtract(a[i], b[i]));
}
}
@Test
public void testMultiply() {
System.out.println("开始测试乘法");
String[] a = new String[]{"a88888","6549876541649875487989121364"};
String[] b = new String[]{"888888","9854225774125485623215"};
String[] c = new String[]{"false","64543962234066102857443470706680302877501810865260"};
for(int i = 0; i<a.length; i++){
assertEquals(c[i],Compute.Multiply(a[i], b[i]));
System.out.println(a[i]+" * "+b[i]+"\n预期结果:"+c[i]+"\n运行结果:"+Compute.Multiply(a[i], b[i]));
}
}
@Test
public void testDivide() {
System.out.println("开始测试除法");
String[] a = new String[]{"a88888","6549876541649875487989121364"};
String[] b = new String[]{"888888","9854225774125485623215"};
String[] c = new String[]{"false","664676"};
for(int i = 0; i<a.length; i++){
assertEquals(c[i],Compute.Divide(a[i], b[i]));
System.out.println(a[i]+" / "+b[i]+"\n预期结果:"+c[i]+"\n运行结果:"+Compute.Divide(a[i], b[i]));
}
}
}
PS:这是第一次写博客,很有新鲜感,主要就是觉得在网上有许多大佬的分享让我受益良多,因此就想把自己的收获总结一下,方便记忆。慢慢来吧!