一般计算器都有长度限制,想做一个突破int,long范围的计算器,我是新手,所以用了非常简单非常笨的一个方法。
在家看到小孩做作业列竖式,就想能不能用列竖式的逻辑来做一个简易计算器,思路也很简单,int类型有长度限制,String没有啊,用String类型来存储数字,把String一个一个拆分为char,然后再做逻辑运算,最后还是用String类型存储结果
目前只粗糙的写了一个加法和乘法,后续如果会考虑把减法和除法加上,以及代码优化
以下是代码,注释的很详细,欢迎大家批评指正
最好做的就是加法跟减法了
加减乘除都有了,功能还需完善,后续会继续补充
/**
*
* 加法
*
* @param num1
* @param num2
* @return
*/
public String add(String num1, String num2) {
// 将字符串拆分为char数组
char[] ch1 = num1.toCharArray();
char[] ch2 = num2.toCharArray();
// result用来存储结果,flag用来标记“满10进1”
StringBuffer result = new StringBuffer();
boolean flag = false;
// 循环条件选用长度更长的参数的length,
for (int a = 1; a <= (ch1.length > ch2.length ? ch1.length : ch2.length); a++) {
int i = 0;
int j = 0;
if (ch1.length - a >= 0) {// 加if判断防止数组下标越界
i = ch1[ch1.length - a] - '0';// 将char转换为int
}
if (ch2.length - a >= 0) {
j = ch2[ch2.length - a] - '0';
}
int n = (i + j) % 10;// 取余数,用于result存储
if (flag) {// 满足“满10加1”的操作
result.append((n + 1) == 10 ? 0 : (n + 1));
if ((i + j + 1) >= 10) {
flag = true;
} else {
flag = false;
}
} else {// 不满足“满10 加1”的操作
result.append(n);
if ((i + j) >= 10) {
flag = true;
} else {
flag = false;
}
}
}
if (flag) {// 最后需再次判断“满10加1”
result.append(1);
}
result.reverse();// 将result反转过来就是最终结果
// System.out.println("加法结果" + result);
return result.toString();
}
减法:将加法稍微变动一下,目前能得到负数,但是还不支持负数作为参数,后续会考虑
/**
* 减法
*
* @param num1
* @param num2
* @return
*/
public String sub(String num1, String num2) {
// 将字符串拆分为char数组
char[] ch1 = num1.toCharArray();
char[] ch2 = num2.toCharArray();
StringBuffer result = new StringBuffer();
boolean flag = false;
int k = compare(num1, num2);
char[] chTemp;
if (k < 0) {
chTemp = ch1;
ch1 = ch2;
ch2 = chTemp;
} else if (k == 0) {
return "0";
}
for (int a = 1; a <= (ch1.length > ch2.length ? ch1.length : ch2.length); a++) {
int i = 0;
int j = 0;
if (ch1.length - a >= 0) {// 加if判断防止数组下标越界
i = ch1[ch1.length - a] - '0';// 将char转换为int
}
if (ch2.length - a >= 0) {
j = ch2[ch2.length - a] - '0';
}
int n = 0;
if (flag) {
if ((i = i - 1) >= j) {
n = i - j;
flag = false;
} else {
n = i + 10 - j;
flag = true;
}
} else {
if (i >= j) {
n = i - j;
flag = false;
} else {
n = i + 10 - j;
flag = true;
}
}
result.insert(0, n);
}
while (result.indexOf("0") == 0) {
if (result.length() > 1) {
result = result.deleteCharAt(0);
} else {
break;
}
}
if (k < 0) {
result.insert(0, "-");
}
return result.toString();
}
乘法:已经添加了计算小数的功能
/**
*
* 乘法
*
* @param num1
* @param num2
* @return
*/
public String mul(String num1, String num2) {
// 判断是否为小数
int indexnum1 = num1.indexOf(".");
int indexnum2 = num2.indexOf(".");
// point用来记录小数位数
int point = 0;
// if判断用来计算小数点后的小数位
if (indexnum1 >= 0) {
point = point + num1.length() - indexnum1 - 1;
}
if (indexnum2 > 0) {
point = point + num2.length() - indexnum2 - 1;
}
// 将小数点去除
num1 = num1.replace(".", "");
num2 = num2.replace(".", "");
// 将字符串拆分为char数组
char[] ch1 = num1.toCharArray();
char[] ch2 = num2.toCharArray();
// 存储下面内层for循环产生的单次结果,用来计算最终结果
List<StringBuffer> list = new ArrayList<StringBuffer>();
for (int i = 1; i <= ch1.length; i++) {
int n1 = ch1[ch1.length - i] - '0';// 将char转换为int
int s = 0;// 用来存储需要进位的十位数
StringBuffer result = new StringBuffer();
for (int j = 1; j <= ch2.length; j++) {
int n2 = ch2[ch2.length - j] - '0';// 将char转换为int
int m = (n1 * n2) % 10;// 取个位数
// 三目判断如果满10取个位数,存入到result中
result.insert(0, (m + s) >= 10 ? (m + s) % 10 : (m + s));
s = (n1 * n2 + s) / 10;// 取十位数,用作进位
}
if (s > 0) {// 内层for每次循环完毕,需判断是否需要进位
result.insert(0, s);
}
// while方法是为了乘数为零的情况下,避免最终结果为多个0 的情况(如果最终结果为多个0 ,就将它改为一个0)
while (result.indexOf("0") == 0) {
if (result.length() > 1) {
result = result.deleteCharAt(0);
} else {
break;
}
}
// System.out.println("乘法单次结果" + result);
list.add(result);// 将单次结果存储到list中
}
// result用来存储最终结果
StringBuffer result = new StringBuffer();
// str用来存储单次结果或者调用add方法后的结果的最末尾的数字,最后会被result使用
StringBuffer str = new StringBuffer();
// add用来存储调用add方法返回的数据
String add = null;
// if判断list长度,长度为1 说明至少有一个乘数为个位数,则只需记录单次结果,即list.get(0)
if (list.size() > 1) {
for (int i = 0; i < list.size() - 1; i++) {
String s1 = "";// 用作存储第一个加数
if (add != null) {
// 截取末尾数字,存储到str,因为每次的末尾数字不需要相加,只需保存,最后交给result使用
String st = add.substring(add.length() - 1, add.length());
str.insert(0, st);
s1 = add.substring(0, add.length() - 1);// 第一个加数
} else {// 第一次循环时候会走else,因为还没有add的数据
result = list.get(i);
String st = list.get(i).substring(list.get(i).length() - 1,
list.get(i).length());
str.insert(0, st);
s1 = result.substring(0, result.length() - 1);// 第一个加数
}
String s2 = list.get(i + 1).toString();// 获取第二个加数
add = add(s1, s2);// 调用add方法,返回结果存储到add字符串中,用于下次循环使用
}
} else {
str = list.get(0);
}
// 如果add不为空,取add的值
if (add != null) {
result = new StringBuffer(add);// 将add结果存储
}
result.append(str);// 最终结果
// while方法是为了乘数为零的情况下,避免最终结果为多个0 的情况(如果最终结果为多个0 ,就将它改为一个0)
while (result.indexOf("0") == 0) {
if (result.length() > 1) {
result = result.deleteCharAt(0);
} else {
break;
}
}
//加上小数点,需先用0补位,避免出现.前面没有0,或数组下标越界
if (point != 0) {
if (result.length() - 1 < point) {
int pointTemp = point - result.length() + 1;
for (int i = 0; i < pointTemp; i++) {
result.insert(0, "0");
}
}
result.insert(result.length() - point, ".");
}
//小数点后如果只有0,省略掉;如88.00省略为88
while (result.lastIndexOf(".") > 0 && result.lastIndexOf("0") == result.length() - 1) {
result.deleteCharAt(result.length() - 1);
if (result.lastIndexOf(".") == result.length() - 1) {
result.deleteCharAt(result.length() - 1);
break;
}
}
// System.out.println("乘法结果" + result);
return result.toString();
}
除法:做起来才知道除法最难了~,目前只是一个雏形,后续会补充和优化,就先不加注释了
目前能够得到小数 只支持正整数运算
/**
* 除法
*
* 目前只支持正整数运算
* 可以得到小数结果
* 最大结果长度暂定1000
*
* @param num1
* @param num2
* @return
*
*/
public String div(String num1, String num2) {
num1 = this.trim(num1);
num2 = this.trim(num2);
if(num2.equals("0")){
return "除数不能为0!";
}
// result存储结果
StringBuffer result = new StringBuffer();
// 临时被除数
String num1Temp = num1;
//存储被除数取余除数的结果
String sub = "";
//用于标记添加小数点操作
boolean flag = false;
//用于存储一位得到的商(商是一位一位得到的)
int temp = -1;
for (int i = 0;; i++) {
if (i + 1 <= num1.length()) {
if (sub.equals("")) {
num1Temp = num1.substring(0, i + 1);
} else {
num1Temp = sub + num1.substring(i, i + 1);
}
} else {
num1Temp = num1Temp + 0;
if (flag == false) {
result.append(".");
flag = true;
}
}
//比较临时被除数和除数的大小
int k = compare(num1Temp, num2);
if (k > 0) {
// for循环得到商的一位数字
for (int j = 2;; j++) {
int comp = compare(num1Temp, mul(num2, j + ""));
if (comp < 0) {
temp = j - 1;
result.append(temp);
break;
} else if (comp == 0) {
temp = j;
result.append(temp);
break;
}
}
//取余
sub = sub(num1Temp, mul(num2, temp + ""));
//设置被除数
num1Temp = sub;
if (sub.equals("0") && i >= num1.length() - 1) {
break;
}
// 测试用,保留1000长度
if (result.length() == 1000) {
break;
}
} else if (k < 0) {
result.append(0);
} else {
result.append(1);
sub = "0";
if (i >= num1.length() - 1) {
break;
}
}
}
// 去除result中无效的0,如008,改为8
while (result.indexOf("0") == 0 && result.indexOf("0.") != 0) {
if (result.length() > 1) {
result = result.deleteCharAt(0);
} else {
break;
}
}
return result.toString();
}
公共方法:用于比较两个数的大小,支持比较小数
/**
*
* 公共方法
* 比较两个数字的大小
* 目前只能是正数,整数和小数都可以
*
* @param ch1
* @param ch2
* @return
*/
public int compare(String str1, String str2) {
str1 = this.trim(str1);
str2 = this.trim(str2);
if (str1.contains(".")||str2.contains(".")) {
String[] ch1 = str1.split("\\.");
String[] ch2 = str2.split("\\.");
int comp = this.compare2(ch1[0], ch2[0]);
if(comp!=0){
return comp;
}
int com = this.compare3(ch1.length==2?ch1[1]:"0",ch2.length==2?ch2[1]:"0");
return com;
}
int comp = this.compare2(str1, str2);
return comp;
}
/**
* private方法
* 比较大小(小数中的整数部分)
* 用于compare()调用
*
* @param str1
* @param str2
* @return
*/
private int compare2(String str1, String str2) {
if (str1.length() > str2.length()) {
return 1;
} else if (str1.length() < str2.length()) {
return -1;
} else {
for (int i = 0; i < str1.length(); i++) {
int ch1=str1.charAt(i)-'0';
int ch2=str2.charAt(i)-'0';
if (ch1 > ch2) {
return 1;
} else if (ch1 < ch2) {
return -1;
}
}
}
return 0;
}
/**
* private方法
* 比较大小(小数中的小数部分)
* 用于compare()调用
*
* 代码有点冗余,后续再优化
*
* @param str1
* @param str2
* @return
*/
private int compare3(String str1, String str2) {
if (!str1.equals(str2)) {
boolean flag = str1.length() > str2.length();
if (flag) {
for (int i = 0; i < str1.length(); i++) {
int ch1=str1.charAt(i)-'0';
int ch2=str2.charAt(i)-'0';
if (ch1 > ch2) {
return 1;
} else if (ch1 < ch2) {
return -1;
}
}
return 1;
}
if (!flag) {
for (int i = 0; i < str1.length(); i++) {
int ch1=str1.charAt(i)-'0';
int ch2=str2.charAt(i)-'0';
if (ch1 > ch2) {
return 1;
} else if (ch1 < ch2) {
return -1;
}
}
return -1;
}
if(str1.length()==str2.length()){
for (int i = 0; i < str1.length(); i++) {
int ch1=str1.charAt(i)-'0';
int ch2=str2.charAt(i)-'0';
if (ch1 > ch2) {
return 1;
} else if (ch1 < ch2) {
return -1;
}
}
return 0;
}
}
return 0;
}
trim方法:用于去掉首尾无效的0
/**
* 公共方法 去除首尾无效的0
*
*
* @param str
* @return
*/
public String trim(String str) {
// 去掉数字前面无效的0,如008省略为8
while (str.startsWith("0") && !str.startsWith("0.")) {
if (str.length() > 1) {
str = str.substring(1, str.length());
}
}
// 小数点后如果只有0,省略掉;如88.00省略为88
while (str.indexOf(".") > 0 && str.endsWith("0")) {
str = str.substring(0, str.length() - 1);
if (str.lastIndexOf(".") == str.length() - 1) {
str = str.substring(0, str.length() - 1);
break;
}
}
return str;
}