可以解析公式的java類例項--可傳入數值運算表示式、含變數的運算表示式
阿新 • • 發佈:2019-02-10
//左括號個數
private int rightBracket = 0;//右括號個數
private int startL = 0;//左括號的位置
private int startR = 0;//右括號的位置
private double answer = 0;
private String leftNumber = "0";
private String rightNumber = "0";
public String Msg = "";
private String formula="";
private int[] sym = new int[4];
private Vector<String> list = new Vector<String>(); //用來存放從字串解析出來的字元
static Vector<Integer> paras = new Vector<Integer>();//用來存放變數引數
/*
*構造方法,以要算的公式為引數
*/
public Formula(String calRule){
this.setFormula(calRule);
}
/*
* 獲得左括號數
*/
private int getLeftBracket(String calRule) {
leftBracket = 0;
startL = calRule.indexOf("(");
if (startL != -1) {
calRule = calRule.substring(startL + 1, calRule.length());
}
while (startL != -1) {
leftBracket++;
startL = calRule.indexOf("(");
calRule = calRule.substring(startL + 1, calRule.length());
}
return leftBracket;
}
/*
* 設定格式
*/
public void setFormula(String calRule){
formula=replaceSubtration(calRule.trim());
formula="("+formula+")";
}
/*
* 為了使公式中支援負數,使用“`”表示減號,使用“-”表示負號,把所有減號換成“‘”
*/
private String replaceSubtration(String vstr){
String tmp="";
String result="";
int startS = vstr.indexOf("-");
if (startS !=-1) {
if (startS > 0) {
tmp = vstr.substring(startS - 1, startS);
if (!"+".equals(tmp) && !"-".equals(tmp) && !"*".equals(tmp) &&!"/".equals(tmp) &&
!"(".equals(tmp)){
result = result + vstr.substring(0, startS) + "`";
}
else
result = result + vstr.substring(0, startS + 1);
}
else
result = result + vstr.substring(0, startS + 1);
vstr = vstr.substring(startS + 1);
}
while (startS != -1) {
startS = vstr.indexOf("-");
if (startS > 0) {
tmp = vstr.substring(startS - 1, startS);
if (!"+".equals(tmp) && !"-".equals(tmp) && !"*".equals(tmp) &&!"/".equals(tmp) &&
!"(".equals(tmp))
result = result + vstr.substring(0, startS) + "`";
else
result = result + vstr.substring(0, startS + 1);
}
else
result = result + vstr.substring(0, startS + 1);
vstr = vstr.substring(startS + 1);
}
result+=vstr;
return result;
}
public String getFormula(){
return formula.replace('`','-').substring(1,formula.length()-1);
}
/*
* 獲得右括號數
*/
private int getRightBracket(String calRule) {
rightBracket = 0;
startR = calRule.indexOf(")");
if (startR != -1) {
calRule = calRule.substring(startR + 1, calRule.length());
}
while (startR != -1) {
rightBracket++;
startR = calRule.indexOf(")");
calRule = calRule.substring(startR + 1, calRule.length());
}
return rightBracket;
}
/*
/*對比左右括號個數
*/
private boolean compareToLR() {
int lb = getLeftBracket(formula);
int rb = getRightBracket(formula);
boolean CTLR = false;
if (lb == rb) {
Msg = "";
CTLR = true;
} else if (lb > rb) {
Msg = "左括弧的個數多於右括弧,請檢查!";
CTLR = false;
} else {
Msg = "左括弧的個數少於右括弧,請檢查!";
CTLR = false;
}
return CTLR;
}
/*
/*檢查公式中是否存在非法字元如(+、-)等
*/
private boolean checkFormula(){
boolean isOk=true;
String[] bracket =new String[2];
String[] sign=new String[4];
bracket[0]="(";
bracket[1]=")";
sign[0]="+";
sign[1]="`";
sign[2]="*";
sign[3]="/";
String vstr="";
for(int i=0;i<bracket.length;i++){
for(int j=0;j<sign.length;j++){
if (i==0)
vstr=bracket[i]+sign[j];
else
vstr=sign[j]+bracket[i];
if (formula.indexOf(vstr)>0){
Msg="公式中存在非法字元"+vstr;
isOk=false;
return isOk;
}
}
}
for(int i=0;i<sign.length;i++){
for(int j=0;j<sign.length;j++){
vstr=sign[i]+sign[j];
if (formula.indexOf(vstr)>0){
Msg="公式中存在非法字元"+vstr;
isOk=false;
return isOk;
}
}
}
if (formula.indexOf("()")>0){
Msg="公式中存在非法字元()";
isOk=false;
}
return isOk;
}
/*
*判斷輸入的字串是否合法
*/
public boolean checkValid(){
if ((formula==null) || (formula.trim().length()<=0) ) {
Msg="請設定屬性calRule!";
return false;
}
return (compareToLR()&&checkFormula());
}
/*返回公式執行結果
*/
public double getResult(){
String formulaStr = "", calRule = "";
double value = 0.0;
calRule = this.formula;
if (checkValid()) {
for (int i = 0; i < leftBracket; i++) {
int iStart=calRule.lastIndexOf("(") + 1;
//獲得最裡層括號裡的內容
formulaStr = calRule.substring(iStart, iStart+calRule.substring(iStart).indexOf(")")).trim();
symbolParse(formulaStr);
value = parseString();
iStart=calRule.lastIndexOf("(");
int iEnd=calRule.substring(iStart).indexOf(")")+1;
calRule = calRule.substring(0,iStart).trim() +
value +
calRule.substring(iStart+iEnd, calRule.length()).trim();
}
}
double tmp = Math.pow(10, 10);
value = Math.round(value * tmp) / tmp;
System.out.println(Msg);
return value;
}
public void FormulaStr(String calRule) {
String formulaStr = "";
if (checkValid()) {
for (int i = 0; i < leftBracket; i++) {
formulaStr = calRule.substring(calRule.lastIndexOf("(") + 1, calRule.indexOf(")")).trim();
symbolParse(formulaStr);
double value = parseString();
String.valueOf(value);
System.out.println("formulaStr=" + formulaStr);
//formulaVal = Double.parseDouble(formulaStr);
System.out.println("formulaVal=" + value);
calRule = calRule.substring(0, calRule.lastIndexOf("(")).trim() + value + calRule.substring(calRule.indexOf(")") + 1, calRule.length()).trim();
System.out.println("calRule=" + calRule);
}
}
}
/*
/*抽取最終括號內資料到List
*/
private void symbolParse(String str) {
list.clear();
int count = 0;
for (int i = 0; i < 4; i++) {
compareMin(str);
while (sym[i] != -1) {
String insStr = str.substring(0, sym[i]).trim();
//判斷insStr是否含有字母
if(containsLetter(insStr)) {
insStr = Integer.toString(parseLetter(insStr, paras.get(count)));
}
list.add(insStr);
insStr = str.substring(sym[i], sym[i] + 1).trim();
list.add(insStr);
str = str.substring(sym[i] + 1, str.length()).trim();
compareMin(str);
count++;
}
}
if (sym[0] == -1 && sym[1] == -1 && sym[2] == -1 & sym[3] == -1) {
if(containsLetter(str)) {
str = Integer.toString(parseLetter(str, paras.get(count)));
}
list.add(str);
}
}
public boolean containsLetter(String insStr) {
boolean isLetter = false;
for(int i=0; i<insStr.length(); i++) {
char ch = insStr.charAt(i);
if(Character.isLetter(ch)) {
isLetter = true;
}
}
return isLetter;
}
public int parseLetter(String insStr, int para) {
if(insStr.charAt(0) == '-') {
para = 0-para;
}
return para;
}
/*
/*迴圈比較賦SubString起始值
*/
private void compareMin(String str) {
int sps = str.indexOf("`");//減法subtration
sym[0] = sps;
int spa = str.indexOf("+");//加法addition
sym[1] = spa;
int spd = str.indexOf("/");//除法division
sym[2] = spd;
int spm = str.indexOf("*");//乘法multiplication
sym[3] = spm;
for (int i = 1; i < sym.length; i++) {
for (int j = 0; j < sym.length - i; j++)
if (sym[j] > sym[j + 1]) {
int temp = sym[j];
sym[j] = sym[j + 1];
sym[j + 1] = temp;
}
}
}
private double parseString()
throws NumberFormatException, StringIndexOutOfBoundsException {
try{
calculate();
return answer;
}catch(Exception e){
Msg="錯誤:" + e.getMessage();
return 0.0;
}
}
/*
* 計算
*/
private void calculate() {
/*
/*處理除法
*/
int spd = list.indexOf("/");
while (spd != -1) {
leftNumber = list.get(spd - 1).toString();
rightNumber = list.get(spd + 1).toString();
list.remove(spd - 1);
list.remove(spd - 1);
list.remove(spd - 1);
double ln = Double.valueOf(leftNumber).doubleValue();
double rn = Double.valueOf(rightNumber).doubleValue();
double answer = ln / rn;
list.add(spd - 1, String.valueOf(answer));
spd = list.indexOf("/");
}
/*
/*處理乘法
*/
int spm = list.indexOf("*");
while (spm != -1) {
leftNumber = list.get(spm - 1).toString();
rightNumber = list.get(spm + 1).toString();
list.remove(spm - 1);
list.remove(spm - 1);
list.remove(spm - 1);
double ln = Double.valueOf(leftNumber).doubleValue();
double rn = Double.valueOf(rightNumber).doubleValue();
double answer = ln * rn;
list.add(spm - 1, String.valueOf(answer));
spm = list.indexOf("*");
}
/*
/*處理減法
*/
int sps = list.indexOf("`");
while (sps != -1) {
leftNumber = list.get(sps - 1).toString();
rightNumber = list.get(sps + 1).toString();
list.remove(sps - 1);
list.remove(sps - 1);
list.remove(sps - 1);
double ln = Double.valueOf(leftNumber).doubleValue();
double rn = Double.valueOf(rightNumber).doubleValue();
double answer = ln - rn;
list.add(sps - 1, String.valueOf(answer));
sps = list.indexOf("`");
}
/*
/*處理加法
*/
int spa = list.indexOf("+");
while (spa != -1) {
leftNumber = list.get(spa - 1).toString();
rightNumber = list.get(spa + 1).toString();
list.remove(spa - 1);
list.remove(spa - 1);
list.remove(spa - 1);
double ln = Double.valueOf(leftNumber).doubleValue();
double rn = Double.valueOf(rightNumber).doubleValue();
double answer = ln + rn;
list.add(spa - 1, String.valueOf(answer));
spa = list.indexOf("+");
}
if (list.size() != 0) {
String result = list.get(0).toString();
if (result == null || result.length() == 0) result = "0";
answer = Double.parseDouble(list.get(0).toString());
}
}
public static void main(String[] args) {
Formula test1 = new Formula("1+2*(3+4)");//測試常規的運算公式
paras.add(4);//為公式裡的變數存資料
paras.add(3);//為公式裡的變數存資料
Formula test2 = new Formula("outPrice-inPrice+10.1");//把兩個變數分別替換成4和3再進行計算
System.out.println(test1.getResult());
System.out.println(test2.getResult());
}
private int rightBracket = 0;//右括號個數
private int startL = 0;//左括號的位置
private int startR = 0;//右括號的位置
private double answer = 0;
private String leftNumber = "0";
private String rightNumber = "0";
public String Msg = "";
private String formula="";
private int[] sym = new int[4];
private Vector<String> list = new Vector<String>();
static Vector<Integer> paras = new Vector<Integer>();//用來存放變數引數
/*
*構造方法,以要算的公式為引數
*/
public Formula(String calRule){
this.setFormula(calRule);
}
/*
* 獲得左括號數
*/
private int getLeftBracket(String calRule) {
leftBracket = 0;
startL = calRule.indexOf("(");
if (startL != -1) {
calRule = calRule.substring(startL + 1, calRule.length());
}
while (startL != -1) {
leftBracket++;
startL = calRule.indexOf("(");
calRule = calRule.substring(startL + 1, calRule.length());
}
return leftBracket;
}
/*
* 設定格式
*/
public void setFormula(String calRule){
formula=replaceSubtration(calRule.trim());
formula="("+formula+")";
}
/*
* 為了使公式中支援負數,使用“`”表示減號,使用“-”表示負號,把所有減號換成“‘”
*/
private String replaceSubtration(String vstr){
String tmp="";
String result="";
int startS = vstr.indexOf("-");
if (startS !=-1) {
if (startS > 0) {
tmp = vstr.substring(startS - 1, startS);
if (!"+".equals(tmp) && !"-".equals(tmp) && !"*".equals(tmp) &&!"/".equals(tmp) &&
!"(".equals(tmp)){
result = result + vstr.substring(0, startS) + "`";
}
else
result = result + vstr.substring(0, startS + 1);
}
else
result = result + vstr.substring(0, startS + 1);
vstr = vstr.substring(startS + 1);
}
while (startS != -1) {
startS = vstr.indexOf("-");
if (startS > 0) {
tmp = vstr.substring(startS - 1, startS);
if (!"+".equals(tmp) && !"-".equals(tmp) && !"*".equals(tmp) &&!"/".equals(tmp) &&
!"(".equals(tmp))
result = result + vstr.substring(0, startS) + "`";
else
result = result + vstr.substring(0, startS + 1);
}
else
result = result + vstr.substring(0, startS + 1);
vstr = vstr.substring(startS + 1);
}
result+=vstr;
return result;
}
public String getFormula(){
return formula.replace('`','-').substring(1,formula.length()-1);
}
/*
* 獲得右括號數
*/
private int getRightBracket(String calRule) {
rightBracket = 0;
startR = calRule.indexOf(")");
if (startR != -1) {
calRule = calRule.substring(startR + 1, calRule.length());
}
while (startR != -1) {
rightBracket++;
startR = calRule.indexOf(")");
calRule = calRule.substring(startR + 1, calRule.length());
}
return rightBracket;
}
/*
/*對比左右括號個數
*/
private boolean compareToLR() {
int lb = getLeftBracket(formula);
int rb = getRightBracket(formula);
boolean CTLR = false;
if (lb == rb) {
Msg = "";
CTLR = true;
} else if (lb > rb) {
Msg = "左括弧的個數多於右括弧,請檢查!";
CTLR = false;
} else {
Msg = "左括弧的個數少於右括弧,請檢查!";
CTLR = false;
}
return CTLR;
}
/*
/*檢查公式中是否存在非法字元如(+、-)等
*/
private boolean checkFormula(){
boolean isOk=true;
String[] bracket =new String[2];
String[] sign=new String[4];
bracket[0]="(";
bracket[1]=")";
sign[0]="+";
sign[1]="`";
sign[2]="*";
sign[3]="/";
String vstr="";
for(int i=0;i<bracket.length;i++){
for(int j=0;j<sign.length;j++){
if (i==0)
vstr=bracket[i]+sign[j];
else
vstr=sign[j]+bracket[i];
if (formula.indexOf(vstr)>0){
Msg="公式中存在非法字元"+vstr;
isOk=false;
return isOk;
}
}
}
for(int i=0;i<sign.length;i++){
for(int j=0;j<sign.length;j++){
vstr=sign[i]+sign[j];
if (formula.indexOf(vstr)>0){
Msg="公式中存在非法字元"+vstr;
isOk=false;
return isOk;
}
}
}
if (formula.indexOf("()")>0){
Msg="公式中存在非法字元()";
isOk=false;
}
return isOk;
}
/*
*判斷輸入的字串是否合法
*/
public boolean checkValid(){
if ((formula==null) || (formula.trim().length()<=0) ) {
Msg="請設定屬性calRule!";
return false;
}
return (compareToLR()&&checkFormula());
}
/*返回公式執行結果
*/
public double getResult(){
String formulaStr = "", calRule = "";
double value = 0.0;
calRule = this.formula;
if (checkValid()) {
for (int i = 0; i < leftBracket; i++) {
int iStart=calRule.lastIndexOf("(") + 1;
//獲得最裡層括號裡的內容
formulaStr = calRule.substring(iStart, iStart+calRule.substring(iStart).indexOf(")")).trim();
symbolParse(formulaStr);
value = parseString();
iStart=calRule.lastIndexOf("(");
int iEnd=calRule.substring(iStart).indexOf(")")+1;
calRule = calRule.substring(0,iStart).trim() +
value +
calRule.substring(iStart+iEnd, calRule.length()).trim();
}
}
double tmp = Math.pow(10, 10);
value = Math.round(value * tmp) / tmp;
System.out.println(Msg);
return value;
}
public void FormulaStr(String calRule) {
String formulaStr = "";
if (checkValid()) {
for (int i = 0; i < leftBracket; i++) {
formulaStr = calRule.substring(calRule.lastIndexOf("(") + 1, calRule.indexOf(")")).trim();
symbolParse(formulaStr);
double value = parseString();
String.valueOf(value);
System.out.println("formulaStr=" + formulaStr);
//formulaVal = Double.parseDouble(formulaStr);
System.out.println("formulaVal=" + value);
calRule = calRule.substring(0, calRule.lastIndexOf("(")).trim() + value + calRule.substring(calRule.indexOf(")") + 1, calRule.length()).trim();
System.out.println("calRule=" + calRule);
}
}
}
/*
/*抽取最終括號內資料到List
*/
private void symbolParse(String str) {
list.clear();
int count = 0;
for (int i = 0; i < 4; i++) {
compareMin(str);
while (sym[i] != -1) {
String insStr = str.substring(0, sym[i]).trim();
//判斷insStr是否含有字母
if(containsLetter(insStr)) {
insStr = Integer.toString(parseLetter(insStr, paras.get(count)));
}
list.add(insStr);
insStr = str.substring(sym[i], sym[i] + 1).trim();
list.add(insStr);
str = str.substring(sym[i] + 1, str.length()).trim();
compareMin(str);
count++;
}
}
if (sym[0] == -1 && sym[1] == -1 && sym[2] == -1 & sym[3] == -1) {
if(containsLetter(str)) {
str = Integer.toString(parseLetter(str, paras.get(count)));
}
list.add(str);
}
}
public boolean containsLetter(String insStr) {
boolean isLetter = false;
for(int i=0; i<insStr.length(); i++) {
char ch = insStr.charAt(i);
if(Character.isLetter(ch)) {
isLetter = true;
}
}
return isLetter;
}
public int parseLetter(String insStr, int para) {
if(insStr.charAt(0) == '-') {
para = 0-para;
}
return para;
}
/*
/*迴圈比較賦SubString起始值
*/
private void compareMin(String str) {
int sps = str.indexOf("`");//減法subtration
sym[0] = sps;
int spa = str.indexOf("+");//加法addition
sym[1] = spa;
int spd = str.indexOf("/");//除法division
sym[2] = spd;
int spm = str.indexOf("*");//乘法multiplication
sym[3] = spm;
for (int i = 1; i < sym.length; i++) {
for (int j = 0; j < sym.length - i; j++)
if (sym[j] > sym[j + 1]) {
int temp = sym[j];
sym[j] = sym[j + 1];
sym[j + 1] = temp;
}
}
}
private double parseString()
throws NumberFormatException, StringIndexOutOfBoundsException {
try{
calculate();
return answer;
}catch(Exception e){
Msg="錯誤:" + e.getMessage();
return 0.0;
}
}
/*
* 計算
*/
private void calculate() {
/*
/*處理除法
*/
int spd = list.indexOf("/");
while (spd != -1) {
leftNumber = list.get(spd - 1).toString();
rightNumber = list.get(spd + 1).toString();
list.remove(spd - 1);
list.remove(spd - 1);
list.remove(spd - 1);
double ln = Double.valueOf(leftNumber).doubleValue();
double rn = Double.valueOf(rightNumber).doubleValue();
double answer = ln / rn;
list.add(spd - 1, String.valueOf(answer));
spd = list.indexOf("/");
}
/*
/*處理乘法
*/
int spm = list.indexOf("*");
while (spm != -1) {
leftNumber = list.get(spm - 1).toString();
rightNumber = list.get(spm + 1).toString();
list.remove(spm - 1);
list.remove(spm - 1);
list.remove(spm - 1);
double ln = Double.valueOf(leftNumber).doubleValue();
double rn = Double.valueOf(rightNumber).doubleValue();
double answer = ln * rn;
list.add(spm - 1, String.valueOf(answer));
spm = list.indexOf("*");
}
/*
/*處理減法
*/
int sps = list.indexOf("`");
while (sps != -1) {
leftNumber = list.get(sps - 1).toString();
rightNumber = list.get(sps + 1).toString();
list.remove(sps - 1);
list.remove(sps - 1);
list.remove(sps - 1);
double ln = Double.valueOf(leftNumber).doubleValue();
double rn = Double.valueOf(rightNumber).doubleValue();
double answer = ln - rn;
list.add(sps - 1, String.valueOf(answer));
sps = list.indexOf("`");
}
/*
/*處理加法
*/
int spa = list.indexOf("+");
while (spa != -1) {
leftNumber = list.get(spa - 1).toString();
rightNumber = list.get(spa + 1).toString();
list.remove(spa - 1);
list.remove(spa - 1);
list.remove(spa - 1);
double ln = Double.valueOf(leftNumber).doubleValue();
double rn = Double.valueOf(rightNumber).doubleValue();
double answer = ln + rn;
list.add(spa - 1, String.valueOf(answer));
spa = list.indexOf("+");
}
if (list.size() != 0) {
String result = list.get(0).toString();
if (result == null || result.length() == 0) result = "0";
answer = Double.parseDouble(list.get(0).toString());
}
}
public static void main(String[] args) {
Formula test1 = new Formula("1+2*(3+4)");//測試常規的運算公式
paras.add(4);//為公式裡的變數存資料
paras.add(3);//為公式裡的變數存資料
Formula test2 = new Formula("outPrice-inPrice+10.1");//把兩個變數分別替換成4和3再進行計算
System.out.println(test1.getResult());
System.out.println(test2.getResult());
}