java 字串公式計算 ——–轉載

來源:互聯網
上載者:User
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 實現對字串運算式進行簡單的包括函數的運算。
*  @author 時銳
*/
public class AnalyzeCalculate {
/**
* 定義運算子
*/
public static List<String> lc = new ArrayList<String>();
static {
lc.add("+");
lc.add("`");
lc.add("*");
lc.add("/");
}
/**
* 定義邏輯運算子
*/
public static List<String> lj = new ArrayList<String>();
static {
lj.add(">");
lj.add("<");
lj.add("=");
lj.add("!");
}
/**
* int數組注釋,第一個標識:0內建函數 1自訂函數;第二個標識:參數個數
*/
public static Map<String, int[]> funMap = new HashMap<String, int[]>();
static {
// 內建函數,可利用反射機制
funMap.put("abs", new int[] { 0, 1 });
funMap.put("acos", new int[] { 0, 1 });
funMap.put("asin", new int[] { 0, 1 });
funMap.put("atan", new int[] { 0, 1 });
funMap.put("cbrt", new int[] { 0, 1 });
funMap.put("ceil", new int[] { 0, 1 });
funMap.put("cos", new int[] { 0, 1 });
funMap.put("cosh", new int[] { 0, 1 });
funMap.put("exp", new int[] { 0, 1 });
funMap.put("expm1", new int[] { 0, 1 });
funMap.put("floor", new int[] { 0, 1 });
funMap.put("log", new int[] { 0, 1 });
funMap.put("log10", new int[] { 0, 1 });
funMap.put("log1p", new int[] { 0, 1 });
funMap.put("random", new int[] { 0, 1 });
funMap.put("rint", new int[] { 0, 1 });
funMap.put("round", new int[] { 0, 1 });
funMap.put("signum", new int[] { 0, 1 });
funMap.put("sin", new int[] { 0, 1 });
funMap.put("sinh", new int[] { 0, 1 });
funMap.put("sqrt", new int[] { 0, 1 });
funMap.put("tan", new int[] { 0, 1 });
funMap.put("tanh", new int[] { 0, 1 });
funMap.put("max", new int[] { 0, 2 });
funMap.put("min", new int[] { 0, 2 });
// 自訂函數
funMap.put("if", new int[] { 1, 3 });
funMap.put("mod", new int[] { 1, 2 });
funMap.put("int", new int[] { 1, 1 });
}

/**
* 公式初始化轉換
*
* @param str
* @return 處理過的計算客串
*/
public static String strCast(String str) {
str = str.toLowerCase();// 去除空格,變小寫

if (str == null ? true : str.length() == 0)
return "0";
if (!checkFormula(str))
return "0";
str = str.replaceAll("\\*-", "**");
str = str.replaceAll("-\\*", "**");
str = str.replaceAll("/-", "//");
str = str.replaceAll("-/", "//");
str = str.replaceAll("\\+-", "-");
str = str.replaceAll("-\\+", "-");
str = str.replaceAll("-", "`");
str = str.replaceAll("\\*\\*", "*-");
str = str.replaceAll("//", "/-");
str = str.replaceAll(" ", "");
return str;
}

/**
* 檢查公式中括弧出現次數是否正確
*
* @param formulaStr
* @return 公式中的括弧是否成對
*/
public static boolean checkFormula(String formulaStr) {
boolean flag = true;
int count = 0;
for (int i = 0; i < formulaStr.length(); i++) {
String s = String.valueOf(formulaStr.charAt(i));
if ("(".equals(s))
count++;
else if (")".equals(s))
count--;
}
flag = count == 0;
return flag;
}

/**
* 分割函數
*
* @param str
* @param bs
* @return 分割後的客串
*/
public static String[] spliteFun(String str, String bs) {
List<String> list = new ArrayList<String>();
String bds = "";
int bracket = 0;
int len = str.length();
for (int i = 0; i < len; i++) {
String s = String.valueOf(str.charAt(i));
if ("(".equals(s)) {
bracket++;
} else if (")".equals(s)) {
bracket--;
}

if (bracket == 0 && bs.equals(s)) {
list.add(bds);
bds = "";
continue;
}

bds += s;
}

list.add(bds);

String[] ss = new String[list.size()];
for (int i = 0; i < list.size(); i++) {
ss[i] = list.get(i);
}

return ss;
}

/**
* 使用者自訂函數
*
* @param str
* @param funStr
* @return 處理使用者自訂函數
*/
public static String customFun(String str, String funStr) {
String reval = "0";

String[] gss = spliteFun(str, ",");
if ("if".equals(funStr)) {
if (compare(gss[0])) {
reval = calculate(gss[1]);
} else {
reval = calculate(gss[2]);
}
} else if ("mod".equals(funStr)) {
double d2 = new Double(calculate(gss[1]));
if (d2 == 0)
return reval;
double d1 = new Double(calculate(gss[0]));
reval = (d1 % d2) + "";
} else if ("int".equals(funStr)) {
reval = Math.floor(new Double(calculate(gss[0]))) + "";
}
return reval;
}

/**
* 邏輯運算式判斷
* @param str
* @return true or false
*/
public static boolean compare(String str) {
boolean flag = false;
boolean bs = false;
int len = str.length();
int bracket = 0;
String ljbds = "";
double d_left = 0;
double d_right = 0;

for (int i = 0; i < len; i++) {
String s = String.valueOf(str.charAt(i));
if ("(".equals(s)) {
bracket++;
} else if (")".equals(s)) {
bracket--;
}

if (bracket == 0 && lj.contains(s)) {
for (int j = i; j < len; j++) {
String ts = String.valueOf(str.charAt(j));
if (lj.contains(ts)) {
ljbds += ts;
} else {
bs = true;
break;
}
}
}
if (bs)
break;
}

String[] s = str.split(ljbds);
d_left = new Double(calculate(s[0]));
d_right = new Double(calculate(s[1]));

if ("<".equals(ljbds)) {
if (d_left < d_right)
return true;
} else if (">".equals(ljbds)) {
if (d_left > d_right)
return true;
} else if ("=".equals(ljbds)) {
if (d_left == d_right)
return true;
} else if (">=".equals(ljbds)) {
if (d_left >= d_right)
return true;
} else if ("<=".equals(ljbds)) {
if (d_left <= d_right)
return true;
} else if ("<>".equals(ljbds) || "!=".equals(ljbds)) {
if (d_left != d_right)
return true;
}

return flag;
}

/**
* 遞迴調用運算
*
* @param str
* @return String
*/
public static String calculate(String str) {

String reval = "";
String bds = "";
int bracket = 0;// 對應括弧個數
int pos = 0;
boolean title = false;

if (str.substring(0, 1).equals("`")) {
str = str.substring(1);
title = true;
}

int len = str.length();

for (int i = 0; i < len; i++) {
String s = String.valueOf(str.charAt(i));
pos = i;
bracket = 0;
if (!lc.contains(s)) {// 如果沒遇到運算子
if ("(".equals(s)) {// 如果遇到左括弧
if (funMap.containsKey(bds)) {// 如果左括弧前是函數
for (int j = i + 1; j < len; j++) {// 從左括弧後開始迴圈
pos++;// 累計移動字元位元
String ts = String.valueOf(str.charAt(j));// 單個字元
// reval+=ts;
if ("(".equals(ts))// 如果是左括弧累計
bracket++;
else if (")".equals(ts)) {// 如果是右括弧進行減少
bracket--;
if (bracket == -1) {// 如果是-1,標識括弧結束
reval = reval.substring(0, reval.length()
- bds.length());// 重新獲得去掉函數頭的運算式
reval += funCalculate(str.substring(i + 1,
j), bds);// 運算式加上函數結果,形成新運算式
i = pos;// 計數器增加
bds = "";// 函數頭清空
break;// 退出本次迴圈
}
}
}
} else {// 如果是普通運算
for (int j = i + 1; j < len; j++) {
pos++;
String ts = String.valueOf(str.charAt(j));
if ("(".equals(ts))
bracket++;
else if (")".equals(ts)) {
bracket--;
if (bracket == -1) {
reval += calculate(str
.substring(i + 1, pos));
i = pos;
bds = "";
break;
}
}
}
}
} else {// 累加總運算式和最後一個運算數(或函數)
bds += s;
reval += s;
}
} else {// 遇到運算子最後一個運算數(或函數)清空
bds = "";
reval += s;
}
}

if (title)
reval = "-" + reval;
return szys(reval);
}

/**
* 函數運算
*
* @param gs
* @param flag
* @return String
*/
public static String funCalculate(String gs, String funStr) {
String rval = "0";
if (funMap.containsKey(funStr)) {
int[] csi = funMap.get(funStr);
try {
if (csi[0] == 0) {// java內建函式,通過反射調用
Class[] cs = new Class[csi[1]];
Object[] objs = new Object[csi[1]];
String[] gss = zlcs(gs);
for (int i = 0; i < csi[1]; i++) {
cs[i] = double.class;
objs[i] = new Double(calculate(gss[i]));
}
Class cls = Class.forName("java.lang.Math");
Method m = cls.getMethod("abs", cs);
rval = String.valueOf(m.invoke(cls, objs));
} else if (csi[0] == 1) {// 自訂函數
rval = customFun(gs, funStr);
}
} catch (Exception e) {

}
}

return rval;
}

/**
* 公式裡的參數分割
* @param str
* @return String[]
*/
public static String[] zlcs(String str) {
int len = str.length();
boolean flag = true;
String tstr = "";

for (int i = 0; i < len; i++) {
String s = String.valueOf(str.charAt(i));
if ("(".equals(s)) {
flag = false;
} else if (")".equals(s)) {
flag = true;
}
if (flag && ",".equals(s)) {
tstr += "@";
} else {
tstr += s;
}
}

return tstr.split("@");

}

/**
* 四則運算運算式處理
*
* @param str
* @return String
*/
public static String szys(String gs) {
gs = gs + "+0"; // 因為下面的計算是遇到符號才進行,所以多加入一個計算符號,不影響值.
String c1 = "";// 第一個運算子號
String c2 = "";// 第二個運算子號
String s1 = "";// 第一個運算數
String s2 = "";// 第二個運算數
String s3 = "";// 第三個運算數

int len = gs.length();
for (int i = 0; i < len; i++) {
String s = String.valueOf(gs.charAt(i));// 獲得該位置字元並轉換成字串做比較

if (lc.contains(s)) { // 如果是運算子號
if (c1.length() == 0)// 如果第一個運算子號為空白,加入
c1 = s;
else if (c2.length() == 0) {// 否則,如果第二個運算子號為空白,加入
c2 = s;// 第二個運算子號
if ("+".equals(c2) || "`".equals(c2)) {// 如果第二個運算子號層級低,那麼進行計算
s1 = _4zys(s1, c1, s2);// 第一個和第二個數計算
c1 = c2;// 儲存第二個運算子,其他為空白
c2 = "";
s2 = "";
}
} else {// 上述都儲存過
if ("+".equals(s) || "`".equals(s)) {// 如果第三個運算子層級低,進行運算
s2 = _4zys(s2, c2, s3);// 先算第二三個數,儲存至第二個
s1 = _4zys(s1, c1, s2);// 再算第一二個,儲存至第一個
c1 = s;// 儲存當前運算子,其他為空白
s2 = "";
c2 = "";
s3 = "";
} else {// 如果第三個運算子層級高
s2 = _4zys(s2, c2, s3);// 先算第二三個數,儲存至第二個
c2 = s;// 前面不動,儲存運算子
s3 = "";
}
}
} else if (s1.length() > 0 && c1.length() > 0 && c2.length() == 0) {// 如果第一個數,第一個運算子已儲存,第二個運算子未儲存,儲存第二哥數
s2 += s;
} else if (c1.length() == 0) {// 如果沒有運算子,儲存第一個數
s1 += s;
} else if (s1.length() > 0 && s2.length() > 0 && c1.length() > 0
&& c2.length() > 0) {// 如果第一二個數和運算子都有,儲存第三個數
s3 += s;
}
}
return s1;
}

/**
* 基本四則運算
*
* @param c1
*            運算數1
* @param s1
*            運算子(加減乘除)
* @param c2
*            運算數2
* @return String
*/
public static String _4zys(String c1, String s1, String c2) {
String reval = "0";

try {
double ln = Double.valueOf(c1).doubleValue();
double rn = Double.valueOf(c2).doubleValue();
if ("+".equals(s1)) {
return (ln + rn) + "";
} else if ("`".equals(s1)) {
return (ln - rn) + "";
} else if ("*".equals(s1)) {
return (ln * rn) + "";
} else if ("/".equals(s1)) {
if (rn == 0)
return reval;
else
return (ln / rn) + "";
}
} catch (Exception e) {
} finally {
}

return reval;
}

/**
* 測試
* @param args
*/
public static void main(String[] args) {

String gs = "if(4 > 3,if( ( 2 - 1 ) /  ( 0.0001 ) * 3 > 3  , ( 2 - ( 2 - 1 ) /  ( 0.0001 ) * 3  ) * 0.8 ,0),  ( 2 + ( 3 - 2 ) /  ( 0.0001 ) *1  )  * 1)";
// 進行四則運算獲得結果
System.out.println(szys(strCast("3-4*-5+5")));
System.out.println(calculate(strCast("3-4*-5+5")));
// 函數運算結果
System.out
.println(calculate(strCast("3+abs(mod(4,if(2>3,1,3))-abs(2*4))*5+5")));

System.out.println(calculate(strCast("if(0.0*2>=10.0,0,10.0-0.0*2)")));

System.out.println(calculate(strCast("if(0<2,(10.0-0*5)*0.8,0)")));

System.out.println(calculate(strCast("-10/0")));

}

}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.