📄 expressionanalyze.java
字号:
//ExpressionsAnalyze.java - 计算公式分析
/*
关于与用法的例子如下:
String expression = "num1 * num2 -num3/num1";
try{
ExpressionAnalyze analyze = new ExpressionAnalyze(expression,12,10,6);
catch(Exception e){
System.out.println(e.toString());
}
double temp = analyze.getResult();
System.out.println(temp);
需要注意的问题:
1. 一定要用try----catch语句;
2. 目前构造函数可以有四种情况:
a. 只有一个参数,用于接收公式,如 ExpressionAnalyze("abs(36-56)+90");
b. 两个参数,第一个用于接收公式,第二个用于接收传值参数的值,
如 ExpressionAnalyze("cos(num)+45",926);
c. 三个参数,第一个用于接收公式,另外两个用于接收传值参数的值,
如ExpressionAnalyze("cos(num)+flag",26,36);
d. 四个参数,第一个用于接收公式,另外三个用于接收传值参数的值,
如ExpressionAnalyze("cos(num)+num1*num2",6,10,32);
3. 所有的输入值和返回值均用double类型以提高精度;
4. 公式中可以包含空格,ExpressionAnalyze 中包含有处理空格的 method 清除其中的空格;
5. 目前支持的运算符包括 + - * / ( ) %(求余数) abs(求绝对值)
acos(反余弦) asin(反正弦) atan(反正切) cbrt(开立方)
ceil(求比被操作数大的最小整数) cos(余弦) cosh(双曲余弦函数)
exp(求ex ) floor(求比操作数小的最大整数) expm1(返回ex -1)
log(求以e为底的对数) log10(求以10为底的对数) log1p(返回1和被操作数和的自然对数)
rint(返回和被操作数最接近的整数的double形式) round(四舍五入,返回long)
signum(正负号函数) sin(正弦函数) sinh(双曲正弦) sqrt(开平方)
tan(正切) tanh(双曲正切) toDegrees(将弧度转化为角度)
toRadians(将角度转化为弧度)共 31 种,并且括号可以嵌套使用。
各种运算符的意义:
6. 负号"-"也可以正常使用,不过在使用中被操作数要加括号,如 (-5);
但是公式开头的符号可以不带括号,如 expression = "-cos(PI)+E";
7. 目前支持的常量包括:
a. 自然对数的底 "e",所用的符号为 "E"
b. 圆周率 "∏" ,所用的符号为 "PI"用法如 expression = "5 + cos (PI)";
8. 公式中也支持科学技术法,如 12.3e6 或者 12.3E6
*/
package ddpie.expressionanalyze;
public class ExpressionAnalyze {
//接受一个表达式参数的构造函数
public ExpressionAnalyze(String expr) throws Exception{
this.expr = expr;
numOfParameter = 0;
try{
clearBlank();
seekOutElem();
compute();
}
catch (Exception e){
throw new Exception(e.toString());
}
}
//接受一个表达式参数、一个传值参数的构造函数
public ExpressionAnalyze(String expr,double value1) throws Exception{
this.expr = expr;
numOfParameter = 1;
this.value1 = value1;
try{
clearBlank();
seekOutElem();
compute();
}
catch (Exception e){
throw new Exception(e.toString());
}
}
//接受一个表达式参数、两个传值参数的构造函数
public ExpressionAnalyze(String expr,double value1,double value2)
throws Exception
{
this.expr = expr;
numOfParameter = 2;
this.value1 = value1;
this.value2 = value2;
try{
clearBlank();
seekOutElem();
compute();
}
catch (Exception e){
throw new Exception(e.toString());
}
}
//接受一个表达式参数、三个传值参数的构造函数
public ExpressionAnalyze(String expr,double value1,double value2,double value3)
throws Exception
{
this.expr = expr;
numOfParameter = 3;
this.value1 = value1;
this.value2 = value2;
this.value3 = value3;
try{
clearBlank();
seekOutElem();
compute();
}
catch (Exception e){
throw new Exception(e.toString());
}
}
//清除expr中的空格
private void clearBlank() throws Exception{
//清除expr末尾的空格
expr = expr.trim();
char [] exprArray = new char[expr.length()];
//将expr中的元素复制到数组exprArray中
for(int i = expr.length()-1;i >= 0;i--)
exprArray[i] = expr.charAt(i);
//逐个将空格清除
for(int i = expr.length()-1;i >= 0;i--){
int j;
if(exprArray[i] ==' '){
j = i;
while(j < exprArray.length - 1){
exprArray[j] = exprArray[j + 1];
j++;
}
exprArray[exprArray.length - 1] = ' ';
}
}
//将数组形式转换成StringBuffer形式
StringBuffer exprStrBuf = new StringBuffer("");
for(int i = 0;i < exprArray.length;i++){
exprStrBuf.insert(i,exprArray[i]);
}
//将StringBuffer形式转换成String形式
expr = exprStrBuf.toString().trim();
if(expr.length() == 0)
throw new Exception("the length of the expression is 0");
}
//将字符串中的变量、常量、运算符挑出
private void seekOutElem() throws Exception{
int minLocation;
int startPoint = 0;
boolean isKeyword;
do{
minLocation = expr.length();
isKeyword = false;
for(int i = 0;i < keywords.length;i++) {
int kwdLocation = expr.substring(startPoint).indexOf(keywords[i]);
if(kwdLocation == -1)
kwdLocation = expr.length();
else
kwdLocation += startPoint;
//如果是运算符
if(kwdLocation == startPoint &&
(keywords[i].equals("(") ||
keywords[i].length() == 1 ||
expr.charAt(startPoint + keywords[i].length()) == '('
)
)
{
//如果链表为空
if(elemList == null){
elemList = new ElemList (keywords[i]);
current = elemList;
current.isOperator = true;
}
//如果链表不空
else{
current.next = new ElemList (keywords[i]);
current = current.next;
current.isOperator = true;
}
isKeyword = true;
break;
}
if(minLocation > kwdLocation)
minLocation = kwdLocation;
}
//如果不是运算符
if(!isKeyword){
//如果链表为空
if(elemList == null){
elemList = new ElemList (expr.substring(startPoint,minLocation));
current = elemList;
current.isOperator = false;
}
//如果链表不空
else{
current.next = new ElemList (expr.substring(startPoint,minLocation));
current = current.next;
current.isOperator = false;
}
}
startPoint += current.data.length();
}while(startPoint < expr.length());
//公式末尾添加"#"
current.next = new ElemList ("#");
current = current.next;
current.isOperator = true;
}
//计算最终的结果
private void compute() throws Exception{
//处理公式开头的负号
if(elemList.data.equals("-")){
ElemList temp = new ElemList ("0");
temp.next = elemList;
elemList = temp;
}
for(current = elemList;current.next != null;current = current.next){
//处理负号
if(current.data.equals("(") && current.next.data.equals("-")){
ElemList temp = new ElemList ("0");
temp.next = current.next;
current.next = temp;
}
//处理常量自然对数的底 e
else if(current.data.equals("E"))
current.data = (new Double(Math.E)).toString();
//处理常量圆周率
else if(current.data.equals("PI"))
current.data = (new Double(Math.PI)).toString();
}
//找出公式中的变量,并对其恰当的赋值
boolean findFirst = false , findSecond = false,findThird = false;
switch(numOfParameter){
case 0 :
for(current = elemList;current != null;current = current.next)
if(!current.isOperator){
//强制类型转换,若转换不成功则说明是变量
try{
Double.parseDouble(current.data);
}
catch (NumberFormatException e){
throw new Exception ("the variable '" + current.data
+ "' needs a value");
}
}
break;
case 1 :
for(current = elemList;current != null;current = current.next)
if(!current.isOperator){
//强制类型转换,若转换不成功则说明是变量
try{
Double.parseDouble(current.data);
}
catch (NumberFormatException e){
findFirst = true;
firstStr = new String(current.data);
firstDou = value1;
break;
}
}
if(!findFirst)
throw new Exception ("there is no variable,the value '" + value1
+"' is not needed");
break;
case 2 :
for(current = elemList;current != null;current = current.next)
if(!current.isOperator){
//强制类型转换,若转换不成功则说明是变量
try{
Double.parseDouble(current.data);
}
catch (NumberFormatException e){
findFirst = true;
firstStr = new String(current.data);
firstDou = value1;
break;
}
}
if(!findFirst)
throw new Exception ("there is no variable,the value '" + value1
+"' is not needed");
for(;current != null;current = current.next)
if(!current.isOperator && !current.data.equals(firstStr)){
//强制类型转换,若转换不成功则说明是变量
try{
Double.parseDouble(current.data);
}
catch (NumberFormatException e){
findSecond = true;
secondStr = new String(current.data);
secondDou = value2;
break;
}
}
if(!findSecond)
throw new Exception ("there are not so much variables,the value '"
+ value2 + "' is not needed");
break;
case 3 :
for(current = elemList;current != null;current = current.next)
if(!current.isOperator){
//强制类型转换,若转换不成功则说明是变量
try{
Double.parseDouble(current.data);
}
catch (NumberFormatException e){
findFirst = true;
firstStr = new String(current.data);
firstDou = value1;
break;
}
}
if(!findFirst)
throw new Exception ("there is no variable,the value '" + value1
+"' is not needed");
for(;current != null;current = current.next)
if(!current.isOperator && !current.data.equals(firstStr)){
//强制类型转换,若转换不成功则说明是变量
try{
Double.parseDouble(current.data);
}
catch (NumberFormatException e){
findSecond = true;
secondStr = new String(current.data);
secondDou = value2;
break;
}
}
if(!findSecond)
throw new Exception ("there are not so much variables,the value '"
+ value2 + "' is not needed");
for(;current != null;current = current.next)
if(!current.isOperator && !current.data.equals(firstStr)
&& !current.data.equals(secondStr)){
//强制类型转换,若转换不成功则说明是变量
try{
Double.parseDouble(current.data);
}
catch (NumberFormatException e){
findThird = true;
thirdStr = new String(current.data);
thirdDou = value3;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -