全文本四则运算算法实现(非预处理四则运算算法)

import javax.swing.JOptionPane;

public class Test1 {
public static void main(String[] args) {
FourCount fc = new FourCount();
StringBuilder sb;
// sb = new StringBuilder("-6*5*10");
// sb = new StringBuilder("-6*5*10*(-2)");
// sb = new StringBuilder("(-9)*(-6)*5*10");
// sb = new StringBuilder("-6*(-2*6/3)");
// sb = new StringBuilder("2*(2*3/6)*3*(4*2)");
// sb = new StringBuilder("8/2*3*(4/2*(3*3*3/(-9)))");
// sb = new StringBuilder("8*(-3*2)");
// sb = new StringBuilder("-2+5-2");
// sb = new StringBuilder("-2+5-2+(-2+3+(-5))");
// sb = new StringBuilder("-2+5-2+(-2+3+(-5+(-2*6)))");
// sb = new StringBuilder("10-2/4*((-2)*3*(-6)-8)-66+(-5)*(-8)+5*(-3)/2-(-9)+3");
sb = new StringBuilder("1+(1+2+(2+3+(3+4+(5*6*(6*7/(8/2))-6)*3)/2)/2)/5-(-5)*3");

//以上测试基本通过!嘿嘿.(新手写的算法, 老鸟勿喷)

new s("计算结果: " + fc.count(sb));
// 2+3-(2+5-(3*2-6/7)-(3+5/2-(4+5))-6)
}
}

/**
* 四则运算类. 支持运算字符:("+"、"-"、"*"、"/"、"("")"、"%"、"."、"0-9")
*/
class FourCount {
private int deepStrL = -1;// 深层文本左边位置
private int deepStrR = -1;// 深层文本右边位置
private int bdsLL = -1;// 表达式左边位置
private int bdsRL = -1;// 表达式右边位置

/**
* 计算四则运算,并返回结果.
*/
public String count(StringBuilder s) {
StringBuilder sb = new StringBuilder(s);// s的备份
String countRosult = "";// 计算结果

do {
// 取得深层文本
countRosult = getBracketDeepString(sb);
// 如果取得的深层文本与欲处理文本一致则返回
if (countRosult.equals(sb.toString())) {
break;
} else {
// 计算乘除加减
countRosult = countRd(new StringBuilder(countRosult));
countRosult = countAs(new StringBuilder(countRosult));

// /////////////// 测试代码 /////////////////
// new s("sb=" + sb.toString() + ",deepStrL=" + deepStrL + ",deepStrR=" + deepStrR);
// /////////////// 测试代码 /////////////////

// 替换计算完毕的结果,以便下次深层搜索
sb.replace(deepStrL, deepStrR, countRosult);

// /////////////// 测试代码 /////////////////
// new s("sb=" + sb.toString() + ", countRosult=" + countRosult);
// /////////////// 测试代码 /////////////////

// /////////////// 测试代码 /////////////////
// new s("sb=" + sb.toString());
// /////////////// 测试代码 /////////////////
}
} while (true);
// 计算乘除加减,然后返回计算结果
countRosult = countRd(new StringBuilder(countRosult));
countRosult = countAs(new StringBuilder(countRosult));

// 如果计算结果为负数,去除括号
if (isCommonNumber(new StringBuilder(countRosult), 0) != -1) {
return countRosult.substring(1, countRosult.length() - 1);
} else {
return countRosult;
}
}

/**
* 搜寻括号,并取得括号深层文本,如:"1+(2+(3+(4+5)+6)+7)+8",取得:"(4+5)"
*/
private String getBracketDeepString(StringBuilder str) {
int l = -1; // 括号"("的位置
int n1 = -1; // 普通数值的返回值
String s1 = ""; // 临时文本

// 如果括号"("不存在,返回-1
if (str.indexOf("(", l + 1) == -1) {
// 返回,不进行处理
return str.toString();
}

// 迭代寻找括号深层文本
do {
// 从寻找到的括号"("位置开始迭代
for (int i = 0; i < str.length(); i++) {
// 取得当前迭代字符
s1 = str.substring(i, i + 1);
// 如果当前字符为括号"("
if (("()").indexOf(s1) != -1) {

// /////////////// 测试代码 /////////////////
// new s(s1.equals("(") + ", " + s1.equals(")"));
// /////////////// 测试代码 /////////////////

if (s1.equals("(")) {
// /////////////// 测试代码 /////////////////
// new s("l=" + l);
// 2+3-(2+5-(3*2-6/7)-(3+5/2-(4+5))-6)
// /////////////// 测试代码 /////////////////

// 计算是否为普通数值表达式
n1 = isCommonNumber(str, i);

// /////////////// 测试代码 /////////////////
// new s("n1=" + n1);
// /////////////// 测试代码 /////////////////

// 如果不是普通数值表达式,而是运算表达式,则将搜索位置设定至当前位置
if (n1 == -1) {
// 记录括号的位置
l = i;
// 到循环尾,准备下一轮的搜索
continue;
} else {
// 将搜索位置设定为普通数值的括号后一位.如:"1+(-5)*2",括号在索引5,则将l设定为5,开始下轮搜索括号"("的准备.
i = n1;
// 到循环尾,准备下一轮的搜索
continue;
}
}
// 如果寻找到括号")",则返回括号深层文本
if (s1.equals(")")) {
// 记录深层文本区间位置
deepStrL = l;
deepStrR = i + 1;
// 返回括号深层文本
return str.substring(l, i + 1);
}
}
}
// 返回不规范(异常)的文本
return str.toString();
} while (true);
}

/**
* 计算能找到的括号内的文本是否为普通数值.如:"1+(-5/3)",其中"(-5/3)"为非普通数值,再如:"1+(-5)-3",其中"(-5)"为普通数值.里面也可以为正整数
*
* @param str
* - 欲计算的可变字符
* @param arg0
* - 开始计算的位置
* @return - 如果是普通数值,返回对应的括号")"位置,如果不是普通数值,而是算术表达式等则返回-1
*/
private static int isCommonNumber(StringBuilder str, int arg0) {
String s1 = "";
// 从括号位置开始搜索,如:"(1+2+3)" → "(1+2+3)"
for (int i = arg0; i < str.length(); i++) {
// 取得单个字符,如:"(1+2+3)" → "("
s1 = str.substring(i, i + 1);
// 判断是否为普通数值表达式
if ((".-0123456789()").indexOf(s1) != -1) {
// 如果在传入的表达式内又找到括号,则返回-1
if (s1.equals("(") && i != arg0) {
return -1;
}
// 如果负号"-"左边不是括号"(",则返回-1
if (s1.equals("-") && i != arg0 + 1) {
return -1;
}
// 如果一直符合数值表达式,且找到括号")",返回里面的负数
if (s1.equals(")")) {
return i;
}
} else {
// 如果发现非普通数值表达式,返回-1
return -1;
}
}
// 如果循环至尾部依旧不存在普通表达式,返回-1(可能此表达式不规范),因为传入的可变字符已经存在括号"(",直至循环结束都未发现括号")",则不规范
return -1;
}

/**
* 获取表达式左边文本
*/
private String getExpreesionsLeft(StringBuilder s, int n) {
String s1 = "";// 临时文本

// /////////////// 测试代码 /////////////////
// new s("s=" + s + ",n=" + n);
// /////////////// 测试代码 /////////////////

for (int i = n - 1; i >= 0; i--) {
if ((".-0123456789()").indexOf(s.substring(i, i + 1)) != -1) {
// 如果运算符左边为")"

// /////////////// 测试代码 /////////////////
// new s("n=" + n + ", i=" + i + ",s.sub=" + s.substring(i, i + 1));
// /////////////// 测试代码 /////////////////

if (i == n - 1 && s.substring(i, i + 1).equals(")")) {
// 迭代寻找运算符
for (int j = i - 1; j >= 0; j--) {

// /////////////// 测试代码 /////////////////
// new s("n=" + n + ", i=" + i + ",s.sub=" + s.substring(j, j + 1));
// /////////////// 测试代码 /////////////////

// 寻找左括号,并取得其负数
if ((".-0123456789(").indexOf(s.substring(j, j + 1)) != -1) {
if (s.substring(j, j + 1).equals("(")) {

// /////////////// 测试代码 /////////////////
// new s("s=" + s + ", n=" + n + ", i=" + i);
// /////////////// 测试代码 /////////////////

bdsLL = j;
s1 = s.substring(j + 1, i);
return s1;
}
} else {
bdsLL = -1;
break;
}
}
}

// /////////////// 测试代码 /////////////////
// new s("1.i="+i+",n="+n);
// /////////////// 测试代码 /////////////////

// 如果找到括号")",则取得该数值表达式并返回
if (s.substring(i, i + 1).equals("(")) {

// /////////////// 测试代码 /////////////////
// new s("1.i="+i+",n="+n);
// /////////////// 测试代码 /////////////////

bdsLL = i + 1;
s1 = s.substring(i + 1, n);
return s1;
}
// 如果循环至头部,则返回该区间数值
if (i == 0) {
bdsLL = i;
s1 = s.substring(i, n);
return s1;
}
// 如果发现负号,且符号前是括号,则返回该区间数值
if (i > 0) {
if (s.substring(i, i + 1).equals("-") && s.substring(i - 1, i).equals("(")) {
bdsLL = i;
s1 = s.substring(i, n);
return s1;
} else if (s.substring(i, i + 1).equals("-")) {
bdsLL = i + 1;
s1 = s.substring(i + 1, n);
return s1;
}
}
} else if ((".0123456789").indexOf(s.substring(i, i + 1)) == -1) {
// /////////////// 测试代码 /////////////////
// new s("2.i=" + i + ",n=" + n);
// /////////////// 测试代码 /////////////////

bdsLL = i + 1;
s1 = s.substring(i + 1, n);
return s1;
}
}
return s1;
}

/**
* 获取表达式右边文本
*/
private String getExpressionRight(StringBuilder s, int n) {
String s1 = "";// 临时文本

// /////////////// 测试代码 /////////////////
// new s("s=" + s + ",n=" + n);
// /////////////// 测试代码 /////////////////

for (int i = n + 1; i < s.length(); i++) {
if ((".-0123456789()").indexOf(s.substring(i, i + 1)) != -1) {
// 如果运算符右边为"("

// /////////////// 测试代码 /////////////////
// new s("1.i=" + i + ",n=" + n + ",s.sub=" + s.substring(i, i + 1));
// /////////////// 测试代码 /////////////////

if (i == n + 1 && s.substring(i, i + 1).equals("(")) {
// 迭代寻找运算符
for (int j = i + 1; j < s.length(); j++) {
// 寻找右括号,并取得其负数
if ((".-0123456789)").indexOf(s.substring(j, j + 1)) != -1) {
if (s.substring(j, j + 1).equals(")")) {

// /////////////// 测试代码 /////////////////
// new s("s=" + s + ", n=" + n + ", i=" + i);
// /////////////// 测试代码 /////////////////

bdsRL = j + 1;
s1 = s.substring(i + 1, j);
return s1;
}
} else {
bdsRL = -1;
break;
}
}
}
// 如果找到括号")",则取得该数值表达式并返回
if (s.substring(i, i + 1).equals(")")) {
bdsRL = i;
s1 = s.substring(n + 1, i);
return s1;
}
// 如果循环至尾部,返回该区间数值
if (i == s.length() - 1) {
bdsRL = i + 1;
s1 = s.substring(n + 1, i + 1);
return s1;
}
// 如果负号不是在第一位
if (s.substring(i, i + 1).equals("-") && i != 0) {
bdsRL = i;
s1 = s.substring(n + 1, i);
return s1;
}
} else if ((".0123456789").indexOf(s.substring(i, i + 1)) == -1 || i == s.length() - 1) {
bdsRL = i;
s1 = s.substring(n + 1, i);
return s1;
}
}
return s1;
}

/**
* 计算乘除
*/
public String countRd(StringBuilder s) {
String L = ""; // 左边运算表达式
String R = ""; // 右边运算表达式
String yunsfh = ""; // 运算符号
int yunsfwz = -1; // 运算符位置
String s1 = ""; // 临时文本

do {
// 初始化
yunsfh = "";
yunsfwz = -1;

// 迭代寻找运算符
for (int i = 0; i < s.length(); i++) {
if (("*").equals(s.substring(i, i + 1))) {
yunsfh = "*";
yunsfwz = i;
break;
} else if (("/").equals(s.substring(i, i + 1))) {
yunsfh = "/";
yunsfwz = i;
break;
}
}

// 如果运算符存在,则处理乘除运算,如果运算符不存在,则返回结果(不管该文不是否被处理过)文本
if (!yunsfh.equals("")) {
// 取得运算符左边的文本
L = getExpreesionsLeft(s, yunsfwz);
// 取得运算符右边文本
R = getExpressionRight(s, yunsfwz);
} else {
break;
}

// /////////////// 测试代码 /////////////////
// new s("乘除运算计算前数据: L=" + L + ",R=" + R + ",LL=" + bdsLL + ",RL=" + bdsRL + ",s=" + s);
// /////////////// 测试代码 /////////////////

// 进行运算
if (yunsfh.equals("*")) {
s1 = Double.valueOf(L).doubleValue() * Double.valueOf(R).doubleValue() + "";
} else if (yunsfh.equals("/")) {
s1 = Double.valueOf(L).doubleValue() / Double.valueOf(R).doubleValue() + "";
} else {
break;
}

// /////////////// 测试代码 /////////////////
// new s("s=" + s + ",s1=" + s1 + ",bool=" + (Double.valueOf(s1).doubleValue() < 0));
// /////////////// 测试代码 /////////////////

// /////////////// 测试代码 /////////////////
// new s("s1=" + s1 + ", s=" + s + ", isCommonNumber=" + isCommonNumber(new StringBuilder(new StringBuilder(s.toString()).replace(bdsLL, bdsRL, s1)), 0));
// /////////////// 测试代码 /////////////////

// 如果计算结果为负数,则加上一对括号
if (Double.valueOf(s1).doubleValue() < 0) {
s1 = "(" + s1 + ")";
}

// 将运算表达式文本替换成计算结果文本
s.replace(bdsLL, bdsRL, s1);

// /////////////// 测试代码 /////////////////
// new s("乘除计算后数据: s=" + s + ",s1=" + s1 + ",LL=" + bdsLL + ",RL=" + bdsRL + ",s=" + s);
// /////////////// 测试代码 /////////////////
} while (true);
// 如果计算结果为普通数值,而不是算术表达式,则去除括号
if (isCommonNumber(s, 0) == -1) {
// 返回计算结果
return s.toString();
} else {
// 迭代去除括号
while (s.substring(0, 1).equals("(") && s.substring(s.length() - 1, s.length()).equals(")")) {
s.replace(0, 1, "");
s.replace(s.length() - 1, s.length(), "");
}
// 如果为负数则加一对括号
if (Double.valueOf(s.toString()).doubleValue() < 0) {
s.insert(0, "(");
s.insert(s.length(), ")");
}
// 返回计算结果
return s.toString();
}
}

/**
* 计算加减
*/
public String countAs(StringBuilder s) {
String L = ""; // 左边运算表达式
String R = ""; // 右边运算表达式
String yunsfh = ""; // 运算符号
int yunsfwz = -1; // 运算符位置
String s1 = ""; // 临时文本

do {
// 初始化
yunsfh = "";
yunsfwz = -1;

// 迭代寻找运算符
for (int i = 0; i < s.length(); i++) {
if (("+").equals(s.substring(i, i + 1))) {
yunsfh = "+";
yunsfwz = i;
break;
} else if (("-").equals(s.substring(i, i + 1)) && i != 0) {
// 如果负号前面为括号"(",则到到循环尾,继续下次搜寻
if (i > 0 && ("-").equals(s.substring(i, i + 1)) && s.substring(i - 1, i).equals("(")) {
continue;
}
yunsfh = "-";
yunsfwz = i;
break;
}
}

// /////////////// 测试代码 /////////////////
// new s("运算符号=\"" + yunsfh + "\"");
// /////////////// 测试代码 /////////////////

// 如果运算符存在,则处理乘除运算,如果运算符不存在,则返回结果(不管该文不是否被处理过)文本
if (!yunsfh.equals("")) {
// 取得运算符左边的文本
L = getExpreesionsLeft(s, yunsfwz);
// 取得运算符右边文本
R = getExpressionRight(s, yunsfwz);
} else {
break;
}

// /////////////// 测试代码 /////////////////
// new s("加减计算前数据: L=" + L + ",R=" + R + ",LL=" + bdsLL + ",RL=" + bdsRL + ",s=" + s);
// /////////////// 测试代码 /////////////////

// 进行运算
if (yunsfh.equals("+")) {
s1 = Double.valueOf(L).doubleValue() + Double.valueOf(R).doubleValue() + "";
} else if (yunsfh.equals("-")) {
s1 = Double.valueOf(L).doubleValue() - Double.valueOf(R).doubleValue() + "";
} else {
break;
}

// /////////////// 测试代码 /////////////////
// new s("s=" + s + ",s1=" + s1 + ",bool=" + (Double.valueOf(s1).doubleValue() < 0));
// /////////////// 测试代码 /////////////////

// /////////////// 测试代码 /////////////////
// new s("s1=" + s1 + ", s=" + s + ", isCommonNumber=" + isCommonNumber(new StringBuilder(new StringBuilder(s.toString()).replace(bdsLL, bdsRL, s1)), 0));
// /////////////// 测试代码 /////////////////

// 如果计算结果为负数,则加上一对括号
if (Double.valueOf(s1).doubleValue() < 0) {
s1 = "(" + s1 + ")";
}

// 将运算表达式文本替换成计算结果文本
s.replace(bdsLL, bdsRL, s1);

// /////////////// 测试代码 /////////////////
// new s("加减运算计算后数据: s=" + s + ",s1=" + s1 + ",LL=" + bdsLL + ",RL=" + bdsRL + ",s=" + s);
// /////////////// 测试代码 /////////////////
} while (true);
if (isCommonNumber(s, 0) != -1) {
// 返回计算结果
return s.toString();
} else {
// 迭代去除括号
while (s.substring(0, 1).equals("(") && s.substring(s.length() - 1, s.length()).equals(")")) {
s.replace(0, 1, "");
s.replace(s.length() - 1, s.length(), "");
}
// 如果为负数则加一对括号
if (Double.valueOf(s.toString()).doubleValue() < 0) {
s.insert(0, "(");
s.insert(s.length(), ")");
}
// 返回计算结果
return s.toString();
}
}
}

/**
* 快捷输出显示类(内部测试专用)
*/
class s {
s(Object o) {
JOptionPane.showMessageDialog(null, o);
}

s(char o) {
JOptionPane.showMessageDialog(null, o + "");
}

s(byte o) {
JOptionPane.showMessageDialog(null, o + "");
}

s(short o) {
JOptionPane.showMessageDialog(null, o + "");
}

s(int o) {
JOptionPane.showMessageDialog(null, o + "");
}

s(long o) {
JOptionPane.showMessageDialog(null, o + "");
}

s(float o) {
JOptionPane.showMessageDialog(null, o + "");
}

s(double o) {
JOptionPane.showMessageDialog(null, o + "");
}
}

posted @ 2015-06-05 21:35  冇乜吔  阅读(185)  评论(0编辑  收藏  举报