JAVA中的eval , 能计算字符串的算数公式(源代码)

a43350860 2009-03-02 05:54:35

public class Arithmetic {

public Arithmetic() {

}

/*操作区*/
private double operation(double n1,double n2,String expression){
if(expression.equals("+")){
return n1 + n2;
} else if(expression.equals("-")){
return n1 - n2;
} else if(expression.equals("*")){
return n1 * n2;
} else if(expression.equals("/")){
return n1 / n2;
}
return 0;
}

/*优先级*/
private int priority(String expression){
if(expression.equals("+") || expression.equals("-")){
return 0;
} else if(expression.equals("*") || expression.equals("/")){
return 1;
} else {
return -1;
}
}

/**
* 判断是否为一个算数运算符
* @param expression 算式运算符
* @return
*/
private boolean isExpression(String expression){
return expression.equals("+") || expression.equals("-") || expression.equals("*") || expression.equals("/") ;
}

/**
* 计算入口
* @param numModel 算式
* @return 结果
*/
public double doAccount(String numModel){
int endIndex = 0;
int startIndex = numModel.indexOf("(",endIndex);
while(startIndex != -1){
endIndex = numModel.indexOf(")", startIndex) + 1;
String segment = numModel.substring(startIndex,endIndex);

double tResult = account(segment.replace("(","").replace(")",""));
numModel = numModel.replace(segment,String.valueOf(tResult));

startIndex = numModel.indexOf("(",0);
}
DecimalFormat format = new DecimalFormat("0.##");
return Double.parseDouble(format.format(account(numModel)));
}

/**
* 核心算法逻辑
* @param numModel 算式
* @return
*/
@SuppressWarnings("unchecked")
private double account(String numModel){
String operators [] = {"\\+","\\-","\\*","\\/","\\(","\\)"};
for(String operator : operators){
numModel = numModel.replaceAll(operator," "+operator+" ");
}
Stack operStack = new Stack();
String numModels[] = numModel.split("\\s+");
String preEle = "";
for(int i = 0; i < numModels.length; i++){
if(isExpression(numModels[i])){
if(preEle == null || preEle.equals("")){
preEle = numModels[i];
} else {
if(priority(preEle) >= priority(numModels[i])){
double d1 = Double.parseDouble(String.valueOf(operStack.pop()));
double d2 = Double.parseDouble(String.valueOf(operStack.pop()));
operStack.push(operation(d2,d1,preEle));
preEle = numModels[i];
} else if(priority(preEle) < priority(numModels[i])){
double d1 = Double.parseDouble(String.valueOf(operStack.pop()));
double d2 = Double.parseDouble(numModels[i+1]);
operStack.push(operation(d1,d2,numModels[i]));
i++;
}
}
} else {
operStack.push(numModels[i]);
}
}

double d1 = Double.parseDouble(String.valueOf(operStack.pop()));
double d2 = Double.parseDouble(String.valueOf(operStack.pop()));
return operation(d2,d1,preEle);
}

/**
* @param args
*/
public static void main(String[] args) {
String numModel = "111.1 * (2 - 1) + (2 - 1) + 50 - 10 * (12 + 3)";
System.out.println(new Arithmetic().doAccount(numModel));
}
}

小弟也是一菜鸟,如果有什么不对的地方,还请大家多多指出来!
...全文
911 11 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
SheLiZi 2009-05-11
  • 打赏
  • 举报
回复
5楼的方法挺好,学习了!
a43350860 2009-03-05
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 bao110908 的回复:]
带有嵌套括号的有问题:
Java codeString numModel = "1 + (2 * (3 + 4) * 5)";
[/Quote]
我把doAccount方法改了一下,解决了括号问题!
代码如下:
/**
* 计算入口
*
* @param numModel
* 算式
* @return 结果
*/
public double doAccount(String numModel) {
try {
int eIndex = numModel.indexOf(")");
int bIndex = numModel.lastIndexOf("(",eIndex);

if(eIndex != -1 && bIndex == -1){
throw new Exception("算式格式不正确!!");
} else if(eIndex == -1 && bIndex != -1) {
throw new Exception("算式格式不正确!!");
}

String segment = numModel.substring(bIndex, eIndex+1);
String tempSegment = segment.replace("(", "").replace(")","");
double tResult = account(tempSegment);
numModel = numModel.replace(segment,String.valueOf(tResult));

if(numModel.indexOf(")") != -1){
return doAccount(numModel);
}

DecimalFormat format = new DecimalFormat("0.##");
return Double.parseDouble(format.format(account(numModel)));
} catch (Exception ex) {
ex.printStackTrace();
}
return 0.0;
}


谢谢bao110908,
你是一个很有经验的人,想得很周到,看得很仔细. 有时间,多多交流!
  • 打赏
  • 举报
回复
带有嵌套括号的有问题:

String numModel = "1 + (2 * (3 + 4) * 5)";
gzfdxy 2009-03-04
  • 打赏
  • 举报
回复
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Arithmetic {

public Arithmetic() {

}

/* 操作区 */
private double operation(double n1, double n2, String expression) {
if (expression.equals("+")) {
return n1 + n2;
} else if (expression.equals("-")) {
return n1 - n2;
} else if (expression.equals("*")) {
return n1 * n2;
} else if (expression.equals("/")) {
return n1 / n2;
}
return 0;
}

/* 优先级 */
private int priority(String expression) {
if (expression != null && !expression.trim().equals("")) {
if (expression.equals("+") || expression.equals("-")) {
return 0;
} else if (expression.equals("*") || expression.equals("/")) {
return 1;
}
}
return -1;
}

/**
* 判断是否为一个算数运算符
*
* @param expression
* 算式运算符
* @return
*/
private boolean isExpression(String expression) {
return expression != null
&& !expression.trim().equals("")
&& (expression.equals("+") || expression.equals("-")
|| expression.equals("*") || expression.equals("/"));
}

/**
* 计算入口
*
* @param numModel
* 算式
* @return 结果
*/
public double doAccount(String numModel) {
try {
int endIndex = 0;
int startIndex = numModel.indexOf("(", endIndex);
while (startIndex != -1) {
endIndex = numModel.indexOf(")", startIndex) + 1;
String segment = numModel.substring(startIndex, endIndex);

double tResult = account(segment.replace("(", "").replace(")",
""));
numModel = numModel.replace(segment, String.valueOf(tResult));

startIndex = numModel.indexOf("(", 0);
}
DecimalFormat format = new DecimalFormat("0.##");
return Double.parseDouble(format.format(account(numModel)));
} catch (Exception ex) {
ex.printStackTrace();
}
return 0.0;
}

/**
* 核心算法逻辑
*
* @param numModel
* 算式
* @return
*/
@SuppressWarnings("unchecked")
private double account(String numModel) throws Exception {

try{
return Double.parseDouble(numModel);
} catch (NumberFormatException ex){}

String operators[] = {"[.0-9]\\+","[.0-9]\\-", "\\*", "\\/", "\\(", "\\)" };
for (int i = 0; i < operators.length; i++) {
if(i == 0 || i == 1){
Pattern pa = Pattern.compile(operators[i]);
Matcher mt = pa.matcher(numModel);
while(mt.find()){
StringBuffer sb = new StringBuffer(mt.group());
sb.insert(1," ");
sb.append(" ");
numModel = numModel.replaceAll(operators[i],sb.toString());
}
} else {
numModel = numModel.replaceAll(operators[i]," "+operators[i]+" ");
}
}

Stack operStack = new Stack();
String numModels[] = numModel.split("\\s+");
String preEle = "";
for (int i = 0; i < numModels.length; i++) {
if (isExpression(numModels[i])) {
if (preEle == null || preEle.equals("")) {
preEle = numModels[i];
} else {
if (priority(preEle) >= priority(numModels[i])) {
double d1 = Double.parseDouble(String.valueOf(operStack
.pop()));
double d2 = Double.parseDouble(String.valueOf(operStack
.pop()));
operStack.push(operation(d2, d1, preEle));
preEle = numModels[i];
} else if (priority(preEle) < priority(numModels[i])) {
double d1 = Double.parseDouble(String.valueOf(operStack
.pop()));
double d2 = Double.parseDouble(numModels[i + 1]);
operStack.push(operation(d1, d2, numModels[i]));
i++;
}
}
} else {
operStack.push(numModels[i]);
}
}

double d1 = Double.parseDouble(String.valueOf(operStack.pop()));
double d2 = Double.parseDouble(String.valueOf(operStack.pop()));
return operation(d2, d1, preEle);
}

/**
* @param args
*/
public static void main(String[] args) {
String numModel = "-1+(+1)-(+1*10)";
System.out.println(new Arithmetic().doAccount(numModel));
}

a43350860 2009-03-04
  • 打赏
  • 举报
回复
把代码重新改进了一下! 不知道还有什么未知的bug ! 嘿嘿!


import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Arithmetic {

public Arithmetic() {

}

/* 操作区 */
private double operation(double n1, double n2, String expression) {
if (expression.equals("+")) {
return n1 + n2;
} else if (expression.equals("-")) {
return n1 - n2;
} else if (expression.equals("*")) {
return n1 * n2;
} else if (expression.equals("/")) {
return n1 / n2;
}
return 0;
}

/* 优先级 */
private int priority(String expression) {
if (expression != null && !expression.trim().equals("")) {
if (expression.equals("+") || expression.equals("-")) {
return 0;
} else if (expression.equals("*") || expression.equals("/")) {
return 1;
}
}
return -1;
}

/**
* 判断是否为一个算数运算符
*
* @param expression
* 算式运算符
* @return
*/
private boolean isExpression(String expression) {
return expression != null
&& !expression.trim().equals("")
&& (expression.equals("+") || expression.equals("-")
|| expression.equals("*") || expression.equals("/"));
}

/**
* 计算入口
*
* @param numModel
* 算式
* @return 结果
*/
public double doAccount(String numModel) {
try {
int endIndex = 0;
int startIndex = numModel.indexOf("(", endIndex);
while (startIndex != -1) {
endIndex = numModel.indexOf(")", startIndex) + 1;
String segment = numModel.substring(startIndex, endIndex);

double tResult = account(segment.replace("(", "").replace(")",
""));
numModel = numModel.replace(segment, String.valueOf(tResult));

startIndex = numModel.indexOf("(", 0);
}
DecimalFormat format = new DecimalFormat("0.##");
return Double.parseDouble(format.format(account(numModel)));
} catch (Exception ex) {
ex.printStackTrace();
}
return 0.0;
}

/**
* 核心算法逻辑
*
* @param numModel
* 算式
* @return
*/
@SuppressWarnings("unchecked")
private double account(String numModel) throws Exception {

try{
return Double.parseDouble(numModel);
} catch (NumberFormatException ex){}

String operators[] = {"[.0-9]\\+","[.0-9]\\-", "\\*", "\\/", "\\(", "\\)" };
for (int i = 0; i < operators.length; i++) {
if(i == 0 || i == 1){
Pattern pa = Pattern.compile(operators[i]);
Matcher mt = pa.matcher(numModel);
while(mt.find()){
StringBuffer sb = new StringBuffer(mt.group());
sb.insert(1," ");
sb.append(" ");
numModel = numModel.replaceAll(operators[i],sb.toString());
}
} else {
numModel = numModel.replaceAll(operators[i]," "+operators[i]+" ");
}
}

Stack operStack = new Stack();
String numModels[] = numModel.split("\\s+");
String preEle = "";
for (int i = 0; i < numModels.length; i++) {
if (isExpression(numModels[i])) {
if (preEle == null || preEle.equals("")) {
preEle = numModels[i];
} else {
if (priority(preEle) >= priority(numModels[i])) {
double d1 = Double.parseDouble(String.valueOf(operStack
.pop()));
double d2 = Double.parseDouble(String.valueOf(operStack
.pop()));
operStack.push(operation(d2, d1, preEle));
preEle = numModels[i];
} else if (priority(preEle) < priority(numModels[i])) {
double d1 = Double.parseDouble(String.valueOf(operStack
.pop()));
double d2 = Double.parseDouble(numModels[i + 1]);
operStack.push(operation(d1, d2, numModels[i]));
i++;
}
}
} else {
operStack.push(numModels[i]);
}
}

double d1 = Double.parseDouble(String.valueOf(operStack.pop()));
double d2 = Double.parseDouble(String.valueOf(operStack.pop()));
return operation(d2, d1, preEle);
}

/**
* @param args
*/
public static void main(String[] args) {
String numModel = "-1+(+1)-(+1*10)";
System.out.println(new Arithmetic().doAccount(numModel));
}
a43350860 2009-03-04
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 bao110908 的回复:]
不一定要用 JDK 6 的 JavaScript Engine 哦,可以看看 BeanShell,BeanShell 是 JSR 274 规范的轻量级动态语言。


Java codeimport bsh.EvalError;
import bsh.Interpreter;

public class Test {

public static void main(String[] args) throws EvalError {
double result = eval("111.1 * (2 - 1) + (2 - 1) + 50 - 10 * (12 + 3)");
System.out.println(result);


Interpr…
[/Quote]
哈哈,太好了,学习了!
  • 打赏
  • 举报
回复
可以采用面向对象的方式来做,可以很方便地进行扩展,比如说再增加个 % 或 ^ 运算符。

你这个在计算 -5 + 9 时存在问题的。

参考这个帖子:http://topic.csdn.net/u/20081011/11/c69b34f6-7605-44a4-918b-a4bed78e8654.html
nihuajie05 2009-03-03
  • 打赏
  • 举报
回复
这个代码真是让人...崩溃啊
  • 打赏
  • 举报
回复
不一定要用 JDK 6 的 JavaScript Engine 哦,可以看看 BeanShell,BeanShell 是 JSR 274 规范的轻量级动态语言。

import bsh.EvalError;
import bsh.Interpreter;

public class Test {

public static void main(String[] args) throws EvalError {
double result = eval("111.1 * (2 - 1) + (2 - 1) + 50 - 10 * (12 + 3)");
System.out.println(result);


Interpreter bsh = new Interpreter();
String expr = "int i = 5; j = 6";
bsh.eval(expr);
System.out.println("i = " + bsh.get("i"));
System.out.println("j = " + bsh.get("j"));
}

private static double eval(String expression) throws EvalError {
Interpreter bsh = new Interpreter();
Number result = (Number)bsh.eval(expression);
return result.doubleValue();
}
}


BeanShell: http://www.beanshell.org/
a43350860 2009-03-03
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 bao110908 的回复:]
可以采用面向对象的方式来做,可以很方便地进行扩展,比如说再增加个 % 或 ^ 运算符。

你这个在计算 -5 + 9 时存在问题的。

参考这个帖子:http://topic.csdn.net/u/20081011/11/c69b34f6-7605-44a4-918b-a4bed78e8654.html
[/Quote]
谢谢! 你的意思是说将运算符工厂化,这样再扩展运算符的时候,只需要修改实现类,而不用修改原程序!
我看看负数应该如何算!
原来JDK1.6有个脚本引擎! 我改明也换个JDK玩玩!
yiliancangbai 2009-03-02
  • 打赏
  • 举报
回复
UP

62,634

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧