这2天比较空,就实现了一个四则运算表达式求解,记录在此,它可以计算,带刮号,带小数,正负数的求解,比如下面的算式,"5*33-(-2)*((16-(100-5.12111))-12.35)",但是没有对算式的合法性做验证,如果输入了不合法的表达式,应该会抛RuntimeException.
类图:
1.CaculateExpress
package com.design.study.composite; import java.math.BigDecimal; public abstract class CaculateExpress { protected BigDecimal value = new BigDecimal(0); public abstract void add(CaculateExpress s); public abstract void subtract(CaculateExpress s); public abstract void multiply(CaculateExpress s); public abstract void divide(CaculateExpress s); public String toString(){ return value.toString(); } }
2.ActualCaculateExpress
package com.design.study.composite; import java.math.BigDecimal; public class ActualCaculateExpress extends CaculateExpress { public ActualCaculateExpress(String s1,String s2, String calExpress){ if("+".equals(calExpress)){ value = new BigDecimal(s1).add(new BigDecimal(s2)); }else if("-".equals(calExpress)){ value = new BigDecimal(s1).subtract(new BigDecimal(s2)); }else if("*".equalsIgnoreCase(calExpress)){ value = new BigDecimal(s1).multiply(new BigDecimal(s2)); }else if("/".equalsIgnoreCase(calExpress)){ value = new BigDecimal(s1).divide(new BigDecimal(s2),10,BigDecimal.ROUND_HALF_EVEN); } } @Override public void add(CaculateExpress s) { value = this.value.add(s.value); } @Override public void divide(CaculateExpress s) { value = this.value.divide(s.value,10,BigDecimal.ROUND_HALF_EVEN); } @Override public void multiply(CaculateExpress s) { value = this.value.multiply(s.value); } @Override public void subtract(CaculateExpress s) { value = this.value.subtract(s.value); } }
3.ActualCaculaterNumber
package com.design.study.composite; import java.math.BigDecimal; public class ActualCaculaterNumber extends CaculateExpress { @Override public void add(CaculateExpress s) { value = this.value.add(s.value); } @Override public void divide(CaculateExpress s) { value = this.value.divide(s.value,10,BigDecimal.ROUND_HALF_EVEN); } @Override public void multiply(CaculateExpress s) { value = this.value.multiply(s.value); } @Override public void subtract(CaculateExpress s) { value = this.value.subtract(s.value); } }
4.PackageExpress
package com.design.study.composite; import java.util.ArrayList; import java.util.List; public class PackageExpress { private boolean flag = false; public List<String> l = new ArrayList<String>(); public PackageExpress(String express) { packageExpress(express); } public void packageExpress(String s) { int startLoc = 0; if (s.startsWith("+") || s.startsWith("-")) { startLoc = 1; } for (int i = startLoc; i < s.length(); i++) { if (!flag) { if (checkExpressIsNumber(s)) { l.add(s); flag = true; return; } if ('+' == s.charAt(i) || '-' == s.charAt(i) || '*' == s.charAt(i) || '/' == s.charAt(i)) { l.add(s.substring(0, i)); l.add(s.substring(i, i + 1)); s = s.substring(i + 1, s.length()); packageExpress(s); } } } } private boolean checkExpressIsNumber(String express){ boolean flag = true; int startLoc = 0; if (express.startsWith("+") || express.startsWith("-")) { startLoc = 1; } for(int i=startLoc;i<express.length();i++){ if ('+' == express.charAt(i) || '-' == express.charAt(i) || '*' == express.charAt(i) || '/' == express.charAt(i)){ flag = false; } } return flag; } }
5.SubExpress
package com.design.study.composite; public class SubExpress { private int startLoc; private int endLoc; private String subExpress; private boolean hasHuahao; public int getStartLoc() { return startLoc; } public void setStartLoc(int startLoc) { this.startLoc = startLoc; } public int getEndLoc() { return endLoc; } public void setEndLoc(int endLoc) { this.endLoc = endLoc; } public String getSubExpress() { return subExpress; } public void setSubExpress(String subExpress) { this.subExpress = subExpress; } public boolean isHasHuahao() { return hasHuahao; } public void setHasHuahao(boolean hasHuahao) { this.hasHuahao = hasHuahao; } }
6.CaculateExpressResult
package com.design.study.composite; import java.math.BigDecimal; import java.util.List; public class CaculateExpressResult extends ActualCaculaterNumber { public CaculateExpressResult(String v) { this.value = new BigDecimal(calGuaHaoExpress(v)); } private String calGuaHaoExpress(String express){ SubExpress s = checkFirst(express); String v = calWithoutGuaHaoExpress(s.getSubExpress()); if(s.isHasHuahao() == false){ return v; } String prvCal = null; if(s.getStartLoc()-2 >= 0){ prvCal = express.substring(s.getStartLoc()-2,s.getStartLoc()-1); } String nextCal = null; if(s.getEndLoc()+2 <= express.length()){ nextCal = express.substring(s.getEndLoc()+1,s.getEndLoc()+2); } if(prvCal != null){ if (!"+".equals(prvCal) && !"-".equals(prvCal) && !"*".equals(prvCal) && !"/".equals(prvCal) && !"(".equals(prvCal) && !")".equals(prvCal)){ throw new RuntimeException("Format error!"); } } if(nextCal != null){ if (!"+".equals(nextCal) && !"-".equals(nextCal) && !"*".equals(nextCal) && !"/".equals(nextCal) && !"(".equals(nextCal) && !")".equals(nextCal)){ throw new RuntimeException("Format error!"); } } express = express.substring(0, s.getStartLoc()-1) + v.toString() + express.substring(s.getEndLoc()+1, express.length()); return calGuaHaoExpress(express); } private String calWithoutGuaHaoExpress(String express){ List<String> l = new PackageExpress(express).l; l = calMulandDivExpress(l); l = calAddandSubExpress(l); return (String)l.get(0); } private List<String> calMulandDivExpress(List<String> l){ for(int i=0;i<l.size();i++){ if("*".equals(l.get(i)) || "/".equals(l.get(i))){ CaculateExpress s = new ActualCaculateExpress(l.get(i-1),l.get(i+1),l.get(i)); l.remove(i-1); l.remove(i-1); l.remove(i-1); l.add(i-1, s.value.toString()); calMulandDivExpress(l); } } return l; } private List<String> calAddandSubExpress(List<String> l){ for(int i=0;i<l.size();i++){ if("+".equals(l.get(i)) || "-".equals(l.get(i))){ CaculateExpress s = new ActualCaculateExpress(l.get(i-1),l.get(i+1),l.get(i)); l.remove(i-1); l.remove(i-1); l.remove(i-1); l.add(i-1, s.value.toString()); calAddandSubExpress(l); } } return l; } private SubExpress checkFirst(String s){ int last = 0; int huahuaCheck = 0; for(int i=0;i<s.length();i++){ if(')' == s.charAt(i)){ last = i; huahuaCheck++; break; } } int prv = s.length(); for(int j=last-1;j>=0;j--){ if('(' == s.charAt(j)){ prv = j; huahuaCheck++; break; } } SubExpress se = new SubExpress(); if(huahuaCheck == 2){ se.setHasHuahao(true); }else if(huahuaCheck == 0){ se.setHasHuahao(false); se.setEndLoc(s.length()); se.setStartLoc(0); se.setSubExpress(s); return se; }else{ throw new RuntimeException("Format error!"); } String t = s.substring(prv+1, last); se.setEndLoc(last); se.setStartLoc(prv+1); se.setSubExpress(t); return se; } }
测试,
package com.design.study.composite; public class CaculateTest { /** * @param args */ public static void main(String[] args) { String express = "5*33-(-2)*((16-(100-5.12111))-12.35)"; System.out.println(new CaculateExpressResult(express)); } }