论坛首页 Java版 企业应用

如何进行表达式求值,就如Javascript中的eval

浏览 6882 次
该帖已经被评为精华帖
作者 正文
时间:2004-04-29
如何对这样的字符串表达进行求值:
"55555.04-25+25*(2.5+100.26)"
   
时间:2004-04-29
我以前用的是beanshell, 代码写起来很方便:

[code:1]
import bsh.Interpreter;

Interpreter i = new Interpreter();
i.eval("result = " + "55555.04-25+25*(2.5+100.26)");
System.out.println(i.get("result"));
[/code:1]
   
0 请登录后投票
时间:2004-04-29
不知有无直接进行逻辑判断的方法,如:3423>55555.04-25+25*(2.5+100.26) 返回true或false
   
0 请登录后投票
时间:2004-04-29
jep is Java Mathematical Expression Parser!
你需要的是数学运算的,jep比较好! 如果java其他方面,beanshell是不错的。 参考地址: http://www.singularsys.com/jep/
   
0 请登录后投票
时间:2004-04-29
用beanshell吧
   
0 请登录后投票
时间:2004-04-29
看了下Beanshell和JEP的文档,两者都不错。JEP功能更强大,用在我这里很合适。如果只是简单的评估表达式的值,Beanshell则简单方便。谢谢大家!
   
0 请登录后投票
时间:2004-05-12
在使用JEP中,发现JEP对 56.1==0.3+55.8 返回总是
0.0(false),可对 6.1==0.3+5.8返回是1.0(true)不知为什么,我已给Nathan Funk发了邮件,linux_china,还有用过JEP的朋友碰到过类似的情况吗?
   
0 请登录后投票
时间:2004-05-14
[code:1]
package expression;

import java.util.*;
import expression.DataInvalidException;
import expression.SOperator;
import expression.DOperator;

/**
* <p>计算字符串表达式的值</p>
* Vesion 1.0功能:
* <p>Description:这个程序演示了如何计算字符串表达式的值,为了将问题简化,在这我
* 只是计算符号格式要求的字符串表达式的值,也就是说不做数据合法性检测。你在测试
* 的时候务必保证表达式正确.看上去应该是这个样子3+2*4+1-5.
* 字符串中的数据必须是个合法的表达式,而且表达式中的运算符号只能是+ - * / ,
* 数字只能是0123456789 ,容许有点”.”号 ,允许操作符和运算数之间有空格
* </p>
*
* Vesion 2.0 功能
* 引入了括号运算符
*
* Vesion 3.0 功能
* 支持JAVA中所有算术运算,而且允许用户自定义运算符号.
* @author 黄云辉
* @version 2.0
* @history:
* 2002 -8 -11 上午 : 完成了字符串表达式的计算。不支持括号运算符
* 2002 -8 -11 晚上 : 支持括号运算符.现在表达式可以是这个样子(3+4)*2+2*(3+3)
* 2002 -8 -13 上午 : 支持JAVA中所有算术运算,而且允许用户自定义运算符号.
*
*为了便于问题的阐述,在此我引入3个概念
*基本运算因子
* 不包括括号的合法字符串表达式(不管它多么复杂)就叫做基本运算因子。比如:
* 30*20,20,30*3+20,log10+2^3,9*3*3/3+3+34*300/3 都是一个基本运算因子.
*基本运算因子具有这样一条性质1:
* 基本运算因子做任何运算后所得结果还是一个基本运算因子.
*基本运算因子规约
* 将多个基本运算因子化成一个基本运算因子的过程叫基本运算因子规约。
*字符串表达式
* 字符串表达式是“左括号(”,基本运算因子的,算术运算符和“右括号)”的集合体.
* 字符串表达式的性质2:
*  1:合法字符串表达式中的“(”,“)”总是成队出现的(要么一个都没有,要么双双“飞“,呵呵)
*  2:最右的左括号相匹配的右括号离它最近.(近水楼台先得月)
*
*下面我们来看看一个合法字符串的基本形态:
* ( (基本运算因子1)* 基本运算因子2)+基本运算因子3
* 由性质1和性质2我们可以知道:
* 我们可以采用一个递归函数将字符串表达式中的括号由里往外一层层“剥”掉,每剥
* 掉一层都要进行一次基本因子规约。所有括号都“剥”光的时候也就是字符串表达式计
* 算的最后一步——计算基本运算因子的结果.
* 所以我们所要做的最重要的事就是计算基本运算因子的结果.
*
* 基本因子如何计算,请看下文。
*/

//---------------------------------------------------------------------
//说明: 用可以通过定义SOperatro/DOperator的实现类,并调用StringExpression
//中的操作符注册方法: registryOp进行注册,可以在字符串表达式中出现自定义
//操作符号. 自定义操作符号必须满足以下条件:
// 1: 必须是合法的标识符号
// 2: 不能包括这些符号 0,1,2,3,4,5,6,7,8,9,.,E,PI
//------------------------------------------------------------------------

/**
*@decription:计算字符串表达式的值,容许带括号.
*
* 现在我门来看看如何实现括号运算符号
* 先让我们看个带括号的字符串表达式: ( ( ( 3+4 ) * 3 + 2 ) *4+3 ) *2
* 兄台,有没有发现:
* 1:“(”和“)”是成队出现的,都是n个(在这n=3)
* 2: 可以看出:他们伴总是离自己最近的(近水楼台先得月,呵呵)
*知道这些就好办了,我门可以用递归函数将括号一层层剥掉
*下面我给你介绍3个将会用到的字符串函数,有请:
*int lastIndexOf(int ch, int fromIndex)
*Returns the index within this string of the last occurrence of the specified
* character, searching backward starting at the specified index.
*
*String substring(int beginIndex, int endIndex)
*Returns a new string that is a substring of this string.
*int indexOf(String str, int fromIndex)
*Returns the index within this string of the first occurrence of the specified
* substring, starting at the specified index.
*哈哈,是不是爽歪了,有了这3个函数我们要做的只是写个很简单的递归函数就可以搞定了.
*具体实施请参看源代码.
*/
public final class StrExpression {
private double result=0;
private Stack SourceStack = new Stack();//字符串表达式计算堆栈
private Stack TempStack = new Stack();


//为了便于操作,用2个hash表来记录操作符信息(这个程序运行效率不是问题)
private static Hashtable op_level = new Hashtable();//操作符信息(操作符号,操作符级别)
private static Hashtable op_class = new Hashtable();//操作符信息(操作符号,计算类)

public StrExpression () {
//注册标准标准操作符号
//第一级别运算符号注册
this.registryOp("n!",1,"expression.SN"); //注册阶乘运算
this.registryOp("dao",1,"expression.SDao"); //注册倒数运算
this.registryOp("sin",1,"expression.SSin"); //注册正玄运算
this.registryOp("cos",1,"expression.SCos"); //注册余玄运算
this.registryOp("tan",1,"expression.STan"); //注册正切运算
this.registryOp("sqrt",1,"expression.SSqrt"); //注册开方运算
this.registryOp("log",1,"expression.SLog"); //注册对数运算
this.registryOp("ln",1,"expression.SLn"); //注册e为底的对数运算
this.registryOp("exp",1,"expression.SExp"); //注册指数运算
this.registryOp("pin",1,"expression.SX2"); //注册平方运算
this.registryOp("li",1,"expression.SX3"); //注册立方运算

//第二级别运算符号注册
this.registryOp("^",2,"expression.DPow"); //注册立方运算
this.registryOp("*",2,"expression.DMul");//注册乘法运算
this.registryOp("/",2,"expression.DDiv");//注册除法运算
this.registryOp("%",2,"expression.DMod");//注册求余数运算
//第三级别运算符号注册
this.registryOp("+",3,"expression.DAdd");//注册加法运算
this.registryOp("-",3,"expression.DDec");//注册减法运算
}

/**
* @description: 注册操作符号信息
* @param value String strOp 操作符
* @param value int strLevel 操作符号级别(操作符号共分了3个级别1.2.3)
* @param value String strClass 操作符号对应的操作类(带上包名)
* @return void
* 说明: 所以有的运算符都必须注册.
*/
public static void registryOp(String strOp,int level,String strClass) {
op_level.put(strOp,new Integer(level));
op_class.put(strOp,strClass);
}
/**
* 获取某操作符的运算级别
* @param value String strOp(操作符)
* @return 操作符级别
*/
private int getLevel( String strOp ) {
String strLevel = op_level.get(strOp).toString();
if ( strLevel == null )
return 0;
else
return Integer.parseInt(strLevel);
}
/**
*判断给定字符串是否是已注册的操作符号
* @param value strOp 待判断操作符号
* @return 如果是已经注册的操作符号,者返回true,否则返回false。
*/
private boolean isOp(String strOp) {
return op_level.containsKey(strOp);
}
/**
* 获取某操作符的运算类
* @param value String strOp(操作符)
* @return 操作符的运算类
*/
private String getClass( String strOp ) {
return (String)op_class.get(strOp);
}
/**
*将字符串表达式分解成运算符号和运算数,并将分解后的字符串保存到堆栈中
* @param value String Expression: 字符串表达式
* @return 运算数和运算符的集合。
* 我采用这样一种方式来分解字符串运算符号:
* 先在各运算符前后都插入‘#’号,然后用StringTokenzier对字符串进行分解.
* 在这我采用了一种比较偷懒的方法插入”#“号(因为这个程序都运算效率没什么
* 要求),具体如何插入,请看源代码.
* 这个方法比较难看懂.我是通过搜索strExpression来定temp的插入位置,所以有个位置
* 差的问题.如果您有什么不明白的地方随时可以和我联系.
*/
private Stack splitStr(String strExpression) throws DataInvalidException {
//----------------------------------------------
HashSet hs = new HashSet();
hs.addAll(op_level.keySet());
hs.add("(");
hs.add(")");
//运算符号集合.
//------------------------------------------------
Iterator i = hs.iterator();//用来遍历运算符
String strOp;
StringBuffer temp = new StringBuffer(strExpression);//为了提高运算效率,引入该变量

//----------------------------------------------------------------------------------
//表答式最前面容许出现‘-’号(负号),可以出现多个负,但没什么意义,所以目前程序
//只许出现一个负号..
String strHead = new String();//用来保存”-”号
while(true) {//
if ( temp.charAt(0)== '-'){
temp.deleteCharAt(0);
strHead +="-";
} else break;
}
//----------------------------------------------------------------------------------
if ( temp.toString().trim().length() == 0)//只有负号的表达式
throw new DataInvalidException("您输入的字符串表达式,不符合格式要求,"+
"导致无法计算,请检测您的输入表达式");

while ( i.hasNext() ) {
int intInsertPos=0;//'#'的插入点.
int intIndex=0;//搜索位置
int intLen=0;//操作符的长度
int intDiff=0;//记录位置差
strOp = i.next().toString();//取出一个运算符
intLen = strOp.length();
strExpression = temp.toString();//temp的值会发生变化,每次插入符号前
//要保证strExpression与temp值相同
while(true) {
intIndex =strExpression.indexOf(strOp,intIndex);
if ( intIndex == -1 ) // 没有找到.
break;
intInsertPos = intIndex + intDiff;//设置插入位置
if (intIndex ==0){
temp.insert(intInsertPos+intLen,'#');//运算符号后面插入“#”
intDiff ++;
}else{
temp.insert(intInsertPos,'#');//运算符号前插入“#”
temp.insert(intInsertPos+intLen+1,'#');//运算符号后面插入“#”
intDiff += 2;
}
intIndex += intLen;//调整搜索位置.

}//end while(true);
}// end while(i .hasNext());
strExpression = strHead +temp.toString();
// 创建个StringTokenizer对象用来提取表达式中的运算符号.
Stack result = new Stack();
StringTokenizer tool = new StringTokenizer(strExpression,"# ");
while(tool.hasMoreElements())
result.push(tool.nextElement());
return result;
}

/**
*@decription: 获取表达式的值.
*@param value : 待计算的字符串表达式
*@return : 字符串表达式的值.
*/
public double getValue(String value) throws DataInvalidException{
int intIndexLeft;//最后一个“(”在字符串value 中的位置
int intIndexRight;//第一个")"在字符串value中的位置.

intIndexLeft = value.lastIndexOf("(");//取得左括号的索引
if ( intIndexLeft == -1 ) {//value中不存在括号.
try {
result = parseValue(value);//如果当value不是个表达式时,会触发异常
} catch (DataInvalidException die) {
throw die;
}//end try -catch
}// end if
else {
intIndexRight = value.indexOf(")",intIndexLeft);//获取与左括号相匹配的右括号。
//将表达式分成 左 中 右三串
String strLeft = value.substring(0,intIndexLeft);//取左串
String strTemp = value.substring(intIndexLeft+1,intIndexRight);//取中串
double dblTemp;
try {
dblTemp = parseValue(strTemp);//计算中串的值.
}catch(DataInvalidException die){
throw die;
}
String strMid = new Double(dblTemp).toString();//得到新的中串
String strRight= value.substring(intIndexRight+1);//获取右串
value = strLeft + strMid + strRight;//重新组合字符串表达式 .
getValue(value);//递归计算.
} //end else
return result;
}//end getValue

/**
*@description:计算运算因子的值
*@param value : 运算因子
*@return: 运算因子的值
*/
private double parseValue( String value )throws DataInvalidException{

this.SourceStack.clear();
this.TempStack.clear();
/*1:数据合法性检测
*如果数据是非法的,则抛出DataInvalidException异常,为了
*简化问题,在这不做数据合法性检测.如果您是做正式产品,这步不能省.
*/

/*2:数据分解
*将字符串的表达式分解成运算符号,和运算数的集合体,并将这些数据压入SourceStack堆栈中.
*如果输入串是"32+33*14-1”那么分解后将会是"32","+","33"*","14","-","1"这个样子。
*
*分解方法:
*为了便于说明问题,假设输入字符串是-32+2*4+3-1
*我门的任务就是将“-32+2*4+3-1“分解成多个字符串: “-32”,”+”,”2”,”*”,”4”,”+”,+”3”,”-“,”1”.
*兄弟门有没有发现:没个运算都是夹在2个数的中间,要是我们在运算符的前面和后面都插入字符“,”,就可以将数字
*和运算符号分开.我门来看看插入符号’,’后字符串的形态: -32,+,2,*,4,*,3,-,1.
*分解这类字符串是StringTokenizer的拿手把戏了,只要将分解标志设为”,”就可以搞定了.
*/
try{
SourceStack.addAll(this.splitStr(value));
}catch (DataInvalidException die) {
throw die;
}
//消除第1级别的运算符
delLevel1();
//将TempStack中的数据挪到SourceStack中,并清除TempStack中内容。这样做没什么特别
//的原因,只是为了沿用上版的某些功能.
SourceStack.addAll((Collection)TempStack.clone());
TempStack.clear();

//如果堆栈中只有一个数据则认为是一个合法数据,否则触发异常.
if (SourceStack.size() == 1) {
try {
return Double.parseDouble(SourceStack.pop().toString());
}catch (Exception e) {
throw new DataInvalidException("您输入的字符串表达式,不符合格式要求,"+
"导致无法计算,请检测您的输入表达式");
}
}
//第2层处理,消除第2级别的运算符号
delLevel2();
//第三层处理,消除第三级别的运算符号
Collections.reverse(TempStack);
return delLevel3();//返回基本运算因子的运算结果 .

}// end StringToValue

//第1层处理,消除第1级别的运算符号
private void delLevel1() {
//第1层处理,消除第1级别的运算符号
String strTemp;//用来保存从SourceStack中弹出来的字符串.

int intSize = SourceStack.size() ;
for( int i=0 ;i< intSize;i++) {
strTemp = (String)SourceStack.pop();
if ( isOp(strTemp) ) {//如果是运算符号
int intLevel = this.getLevel(strTemp);//获取运算级别
if ( intLevel==1) {//
Object objX = TempStack.pop();//取出运算数
String strClass = getClass(strTemp);// 获取类包路径
try {
Class clsCalculate = Class.forName(strClass);
SOperator cal = (SOperator)clsCalculate.newInstance();
TempStack.push(cal.calculate(objX));
}catch(Exception e) {
e.printStackTrace();
}//end try-catch
}//if (intLevel==1)
if ( intLevel==3 ||
intLevel==2 ) {//将2,3级别运算符号进行压栈处理
TempStack.push(strTemp);
}//end if
}//end if ( strOperator.indexOf(strTemp)!=-1 ) //如果是运算符号

if ( isOp(strTemp) == false ) {//如果是运算数
TempStack.push(strTemp);//将运算数直接压栈
}
}//end for
// SourceStack.addAll((Collection)s.clone());
return ;
}
//第2层处理,消除第2级别的运算符号
private void delLevel2() {
//第2层处理,消除第2级别的运算符号
String strTemp;//用来保存从SourceStack中弹出来的字符串.
int intSize = SourceStack.size() ;//堆栈大小

//循环检测2级运算符,并消除之.
for( int i=0 ;i< intSize;i++) {
//注意,程序最多的循环次数是intSize,当表达式中出现*,/号时,循环次数会小
//于intSize次,所以必须加上下面这条语句.
if (SourceStack.isEmpty())
break;
strTemp = SourceStack.pop().toString();
if ( isOp(strTemp) ) {//如果是运算符号
int intLevel = this.getLevel(strTemp);//获取运算级别
if ( intLevel==2) {
Object objX = TempStack.pop();//取出运算数
Object objY = SourceStack.pop();//取出运算数
String strClass = getClass(strTemp);
try {
Class clsCalculate = Class.forName(strClass);
DOperator cal = (DOperator)clsCalculate.newInstance();
TempStack.push(cal.calculate(objX,objY));
}catch(Exception e) {
e.printStackTrace();
}//end try-catch
}//if (intLevel==2)
if ( intLevel==3) {//将3级别运算符号进行压栈处理
TempStack.push(strTemp);
}//end if
}//end if ( strOperator.indexOf(strTemp)!=-1 ) //如果是运算符号

if ( isOp(strTemp) == false ) {//如果是运算数
TempStack.push(strTemp);//将运算数直接压栈
}
}//end for

}//end level2

//第三层处理,消除第三级别的运算符号
private double delLevel3() {
//第三层处理,消除第三级别的运算符号
while(true) {
if ( TempStack.size() == 1 )//如果TempStack中只剩下一项,那么剩下的这项必定
return ( (Double)TempStack.pop() ).doubleValue();//是计算结果.

Object objX = TempStack.pop();//取出运算数
String strOp = TempStack.pop().toString();//获取操作符号
Object objY = TempStack.pop();//取出运算数

String strClass = getClass(strOp);
try {
Class clsCalculate = Class.forName(strClass);
DOperator cal = (DOperator)clsCalculate.newInstance();
TempStack.push(cal.calculate(objX,objY));
}catch(Exception e) {
e.printStackTrace();
}
}//end while
}
}//end StringToValue



//-------------------------------------------------------------------------

//}//end StringExpression.

//=========================================================================================
//标准运算符号的实现类:
// 命名约定:
// 单目运算符的实现类以 S 开头
// 双目运算符的实现类一 D 开头

//================================================================================
//第三级别实现类==================================================================

//加法运算实现类
class DAdd implements DOperator {
public Object calculate(Object op_num1,Object op_num2) throws DataInvalidException {
try {
double x = Double.parseDouble(op_num1.toString());//取被加数
double y = Double.parseDouble(op_num2.toString());//取加数
double result = x + y;
return new Double(result);
} catch (Exception e) {
throw new DataInvalidException("您输入的字符串表达式,不符合格式要求,"+
"导致无法计算,请检测您的输入表达式");
}// end try-catch
}//end calculate
}//end DAdd


//减法运算实现类
class DDec implements DOperator {
public Object calculate(Object op_num1,Object op_num2) throws DataInvalidException {
try {
double x = Double.parseDouble(op_num1.toString());//取被减数数
double y = Double.parseDouble(op_num2.toString());//取减数
double result = x - y;
return new Double(result);
} catch (Exception e) {
throw new DataInvalidException("您输入的字符串表达式,不符合格式要求,"+
"导致无法计算,请检测您的输入表达式");
}// end try-catch
}//end calculate
}//DDec

//================================================================================
//第2级别实现类
//================================================================================
//乘法运算实现类
class DMul implements DOperator {
public Object calculate(Object op_num1,Object op_num2) throws DataInvalidException {
try {
double x = Double.parseDouble(op_num1.toString());//取被乘数
double y = Double.parseDouble(op_num2.toString());//取乘数
double result = x * y;
return new Double(result);
} catch (Exception e) {
throw new DataInvalidException("您输入的字符串表达式,不符合格式要求,"+
"导致无法计算,请检测您的输入表达式");
}// end try-catch
}//end calculate
}//DMul

//除法运算实现类
class DDiv implements DOperator {
public Object calculate(Object op_num1,Object op_num2) throws DataInvalidException {
try {
double x = Double.parseDouble(op_num1.toString());//取被除数
double y = Double.parseDouble(op_num2.toString());//取除数
double result = x / y;
return new Double(result);
} catch (Exception e) {
throw new DataInvalidException("您输入的字符串表达式,不符合格式要求,"+
"导致无法计算,请检测您的输入表达式");
}// end try-catch
}//end calculate
}//DDiv

//求余运算实现类
class DMod implements DOperator {
public Object calculate(Object op_num1,Object op_num2) throws DataInvalidException {
try {
double x = Double.parseDouble(op_num1.toString());//取被除数
double y = Double.parseDouble(op_num2.toString());//取除数
double result = x % y;
return new Double(result);
} catch (Exception e) {
throw new DataInvalidException("您输入的字符串表达式,不符合格式要求,"+
"导致无法计算,请检测您的输入表达式");
}// end try-catch
}//end calculate
}//DDod

//求指数运算实现类
class DPow implements DOperator {
public Object calculate(Object op_num1,Object op_num2) throws DataInvalidException {
try {
double x = Double.parseDouble(op_num1.toString());//取被除数
double y = Double.parseDouble(op_num2.toString());//取除数
double result = Math.pow(x,y);
return new Double(result);
} catch (Exception e) {
throw new DataInvalidException("您输入的字符串表达式,不符合格式要求,"+
"导致无法计算,请检测您的输入表达式");
}// end try-catch
}//end calculate
}//DPow


//================================================================================
//第一级别实现类=================================================================

//求倒数
class SDao implements SOperator {
public Object calculate(Object op_num) throws DataInvalidException {
try {
double x = Double.parseDouble(op_num.toString());//取被除数
double result =1/x;
return new Double(result);
} catch (Exception e) {
throw new DataInvalidException("您输入的字符串表达式,不符合格式要求,"+
"导致无法计算,请检测您的输入表达式");
}// end try-catch
}//end calculate
}//DDiv

//开方
class SSqrt implements SOperator {
public Object calculate(Object op_num) throws DataInvalidException {
try {
double x = Double.parseDouble(op_num.toString());//取被除数
double result =Math.sqrt(x);
return new Double(result);
} catch (Exception e) {
throw new DataInvalidException("您输入的字符串表达式,不符合格式要求,"+
"导致无法计算,请检测您的输入表达式");
}// end try-catch
}//end calculate
}//DSqrt

//正玄
class SSin implements SOperator {
public Object calculate(Object op_num) throws DataInvalidException {
try {
double x = Double.parseDouble(op_num.toString());//取被除数
double result =Math.sin(x);
return new Double(result);
} catch (Exception e) {
throw new DataInvalidException("您输入的字符串表达式,不符合格式要求,"+
"导致无法计算,请检测您的输入表达式");
}// end try-catch
}//end calculate
}//DSin

//正玄
class SCos implements SOperator {
public Object calculate(Object op_num) throws DataInvalidException {
try {
double x = Double.parseDouble(op_num.toString());//取被除数
double result =Math.cos(x);
return new Double(result);
} catch (Exception e) {
throw new DataInvalidException("您输入的字符串表达式,不符合格式要求,"+
"导致无法计算,请检测您的输入表达式");
}// end try-catch
}//end calculate
}//DCos

//正切
class STan implements SOperator {
public Object calculate(Object op_num) throws DataInvalidException {
try {
double x = Double.parseDouble(op_num.toString());//取被除数
double result =Math.tan(x);
return new Double(result);
} catch (Exception e) {
throw new DataInvalidException("您输入的字符串表达式,不符合格式要求,"+
"导致无法计算,请检测您的输入表达式");
}// end try-catch
}//end calculate
}//STan

//exp
class SExp implements SOperator {
public Object calculate(Object op_num) throws DataInvalidException {
try {
double x = Double.parseDouble(op_num.toString());//取被除数
double result =Math.exp(x);
return new Double(result);
} catch (Exception e) {
throw new DataInvalidException("您输入的字符串表达式,不符合格式要求,"+
"导致无法计算,请检测您的输入表达式");
}// end try-catch
}//end calculate
}//SExp

//log
class SLog implements SOperator {
public Object calculate(Object op_num) throws DataInvalidException {
try {
double x = Double.parseDouble(op_num.toString());//取被除数
double result =Math.log(x);
return new Double(result);
} catch (Exception e) {
throw new DataInvalidException("您输入的字符串表达式,不符合格式要求,"+
"导致无法计算,请检测您的输入表达式");
}// end try-catch
}//end calculate
}//SLog

//N!
class SN implements SOperator {
public Object calculate(Object op_num) throws DataInvalidException {
try {
double x = Double.parseDouble(op_num.toString());//取被除数
double result =n(new Double(x).intValue());
return new Double(result);
} catch (Exception e) {
throw new DataInvalidException("您输入的字符串表达式,不符合格式要求,"+
"导致无法计算,请检测您的输入表达式");
}// end try-catch
}//end calculate
private double n(int x) {
if ( x==1 )
return 1;
else
return x*n(x-1);
}
}//SN

//N!
class SX3 implements SOperator {
public Object calculate(Object op_num) throws DataInvalidException {
try {
double x = Double.parseDouble(op_num.toString());//取被除数
double result = Math.pow(x,3);
return new Double(result);
} catch (Exception e) {
throw new DataInvalidException("您输入的字符串表达式,不符合格式要求,"+
"导致无法计算,请检测您的输入表达式");
}// end try-catch
}//end calculate
}//SX3

class SX2 implements SOperator {
public Object calculate(Object op_num) throws DataInvalidException {
try {
double x = Double.parseDouble(op_num.toString());//取被除数
double result = Math.pow(x,2);
return new Double(result);
} catch (Exception e) {
throw new DataInvalidException("您输入的字符串表达式,不符合格式要求,"+
"导致无法计算,请检测您的输入表达式");
}// end try-catch
}//end calculate
}//SX2

class SLn implements SOperator {
public Object calculate(Object op_num) throws DataInvalidException {
try {
double x = Double.parseDouble(op_num.toString());//取被除数
double result = Math.log(x)/Math.log(10);
return new Double(result);
} catch (Exception e) {
throw new DataInvalidException("您输入的字符串表达式,不符合格式要求,"+
"导致无法计算,请检测您的输入表达式");
}// end try-catch
}//end calculate
}//SLn

[/code:1]
   
0 请登录后投票
时间:2004-05-14
[code:1]
package expression;
import expression.DataInvalidException;

//---------------------------------------------------------------------
//说明: 用可以通过定义SOperatro/DOperator的实现类,并调用StringExpression
//中的操作符注册方法: registryOp进行注册,可以在字符串表达式中出现自定义
//操作符号. 自定义操作符号必须满足以下条件:
// 1: 必须是标准的操作符号
// 2: 不能包括这些符号 0,1,2,3,4,5,6,7,8,9,.,E,PI
//------------------------------------------------------------------------

/**
* 定义单目运算符号接口
* 所有的单目运算符的运算类都必须实现该接口
* 因为运算数据来自 hashtable,所以我将程序输入参数设成Object,主要是
* 方便调用,不过在实现中要多做2件事。
* 1:将参数转成double数据,
* 2:将运算结果转成 Object类型的.
*/
public interface SOperator {
public Object calculate( Object op_num ) throws DataInvalidException;
}

package expression;
import expression.DataInvalidException;
//---------------------------------------------------------------------
//说明: 用可以通过定义SOperatro/DOperator的实现类,并调用StringExpression
//中的操作符注册方法: registryOp进行注册,可以在字符串表达式中出现自定义
//操作符号. 自定义操作符号必须满足以下条件:
// 1: 必须是标准的操作符号
// 2: 不能包括这些符号 0,1,2,3,4,5,6,7,8,9,.,E,PI
//------------------------------------------------------------------------

/**
* 定义双目运算符号接口
* 所有的双目运算符的运算类都必须实现该接口
* 因为运算数据来自 hashtable,所以我将程序输入参数设成Object,主要是
* 方便调用,不过在实现中要多做2件事。
* 1:将参数转成double数据,
* 2:将运算结果转成 Object类型的.
*/
public interface DOperator {
public Object calculate( Object op_num1,Object op_num2 ) throws DataInvalidException;
}
//使用
import expression.StrExpression;
public class Test5
{
public static void main(String[] args)
{
//说明: getValue是获取运算结果的唯一方法.
StrExpression se = new StrExpression();
String str="4-3-3";
try
{
System.err.println(se.getValue(str));
}
catch (Exception e)
{
System.out.println(e);
}
}
}

[/code:1]
   
0 请登录后投票
时间:2004-05-14
谢谢 huangyh!我手头也有个类似的代码,可不能完全满足我的要求,我要求在求值时,同时还有复杂的逻辑运算,精度的要求等。
   
0 请登录后投票
论坛首页 Java版 企业应用

跳转论坛:
JavaEye推荐