四则运算表达式求解的简单实现
这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));
}
}