Java计算数学表达式代码详解
Java字符串转换成算术表达式计算并输出结果,通过这个⼯具可以直接对字符串形式的算术表达式进⾏运算,并且使⽤⾮常简单。
这个⼯具中包含两个类 Calculator 和 ArithHelper
Calculator 代码如下:
import java.util.Collections;
import java.util.Stack;
/**
* 算数表达式求值
* 直接调⽤Calculator的类⽅法conversion()
* 传⼊算数表达式,将返回⼀个浮点值结果
* 如果计算过程错误,将返回⼀个NaN
*/
public class Calculator {
private Stack<String> postfixStack = new Stack<String>();
// 后缀式栈
private Stack<Character> opStack = new Stack<Character>();
// 运算符栈
private int[] operatPriority = new int[] { 0, 3, 2, 1, -1, 1, 0, 2 };
// 运⽤运算符ASCII码-40做索引的运算符优先级
public static double conversion(String expression) {
double result = 0;
Calculator cal = new Calculator();
try {
expression = transform(expression);
result = cal.calculate(expression);
}
catch (Exception e) {
// e.printStackTrace();
// 运算错误返回NaN
return 0.0 / 0.0;
}
// return new String().valueOf(result);
return result;
}
/**
* 将表达式中负数的符号更改
*
* @param expression
*      例如-2+-1*(-3E-2)-(-1) 被转为 ~2+~1*(~3E~2)-(~1)
* @return
*/
private static String transform(String expression) {
char[] arr = CharArray();
for (int i = 0; i < arr.length; i++) {
if (arr[i] == '-') {
if (i == 0) {
arr[i] = '~';
} else {
char c = arr[i - 1];
if (c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == 'E' || c == 'e') {
arr[i] = '~';
}
}
}
}
if(arr[0]=='~'||arr[1]=='('){
arr[0]='-';
return "0"+new String(arr);
} else{
return new String(arr);
}
}
/**
* 按照给定的表达式计算
*
* @param expression
*      要计算的表达式例如:5+12*(3+5)/7
* @return
*/
public double calculate(String expression) {
Stack<String> resultStack = new Stack<String>();
prepare(expression);
// 将后缀式栈反转
String firstValue, secondValue, currentValue;
// 参与计算的第⼀个值,第⼆个值和算术运算符
while (!postfixStack.isEmpty()) {
currentValue = postfixStack.pop();
if (!isOperator(currentValue.charAt(0))) {
// 如果不是运算符则存⼊操作数栈中
currentValue = place("~", "-");
resultStack.push(currentValue);
} else {
// 如果是运算符则从操作数栈中取两个值和该数值⼀起参与运算
secondValue = resultStack.pop();
firstValue = resultStack.pop();
// 将负数标记符改为负号
firstValue = place("~", "-");
secondValue = place("~", "-");
String tempResult = calculate(firstValue, secondValue, currentValue.charAt(0));    resultStack.push(tempResult);
}
}
return double.valueOf(resultStack.pop());
}
/**
* 数据准备阶段将表达式转换成为后缀式栈
*
* @param expression
*/
private void prepare(String expression) {
opStack.push(',');
// 运算符放⼊栈底元素逗号,此符号优先级最低
char[] arr = CharArray();
int currentIndex = 0;
// 当前字符的位置
int count = 0;
// 上次算术运算符到本次算术运算符的字符的长度便于或者之间的数值
char currentOp, peekOp;
// 当前操作符和栈顶操作符
for (int i = 0; i < arr.length; i++) {
currentOp = arr[i];
if (isOperator(currentOp)) {
// 如果当前字符是运算符
if (count > 0) {
postfixStack.push(new String(arr, currentIndex, count));
// 取两个运算符之间的数字
}
peekOp = opStack.peek();
if (currentOp == ')') {
// 遇到反括号则将运算符栈中的元素移除到后缀式栈中直到遇到左括号
while (opStack.peek() != '(') {
postfixStack.push(String.valueOf(opStack.pop()));
}
opStack.pop();
} else {
while (currentOp != '(' && peekOp != ',' && compare(currentOp, peekOp)) {
postfixStack.push(String.valueOf(opStack.pop()));
peekOp = opStack.peek();java switch case string
}
opStack.push(currentOp);
}
count = 0;
currentIndex = i + 1;
} else {
count++;
}
}
if (count > 1 || (count == 1 && !isOperator(arr[currentIndex]))) {
// 最后⼀个字符不是括号或者其他运算符的则加⼊后缀式栈中
postfixStack.push(new String(arr, currentIndex, count));
}
while (opStack.peek() != ',') {
postfixStack.push(String.valueOf(opStack.pop()));
/
/ 将操作符栈中的剩余的元素添加到后缀式栈中
}
}
/**
* 判断是否为算术符号
*
* @param c
* @return
*/
private Boolean isOperator(char c) {
return c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')';
}
/**
* 利⽤ASCII码-40做下标去算术符号优先级
*
* @param cur
* @param peek
* @return
*/
public Boolean compare(char cur, char peek) {
// 如果是peek优先级⾼于cur,返回true,默认都是peek优先级要低
Boolean result = false;
if (operatPriority[(peek) - 40] >= operatPriority[(cur) - 40]) {
result = true;
}
return result;
}
/**
* 按照给定的算术运算符做计算
*
* @param firstValue
* @param secondValue
* @param currentOp
* @return
*/
private String calculate(String firstValue, String secondValue, char currentOp) {  String result = "";
switch (currentOp) {
case '+':
result = String.valueOf(ArithHelper.add(firstValue, secondValue));
break;
case '-':
result = String.valueOf(ArithHelper.sub(firstValue, secondValue));
break;
case '*':
result = String.valueOf(ArithHelper.mul(firstValue, secondValue));
break;
case '/':
result = String.valueOf(ArithHelper.div(firstValue, secondValue));
break;
}
return result;
}
}
ArithHelper 代码如下:
public class ArithHelper {
/
/ 默认除法运算精度
private static final int DEF_DIV_SCALE = 16;
// 这个类不能实例化
private ArithHelper() {
}
/**
* 提供精确的加法运算。
*
* @param v1 被加数
* @param v2 加数
* @return 两个参数的和
*/
public static double add(double v1, double v2) {
java.math.BigDecimal b1 = new java.math.String(v1));  java.math.BigDecimal b2 = new java.math.String(v2));  return b1.add(b2).doubleValue();
}
public static double add(String v1, String v2) {
java.math.BigDecimal b1 = new java.math.BigDecimal(v1);
java.math.BigDecimal b2 = new java.math.BigDecimal(v2);
return b1.add(b2).doubleValue();
}
/**
* 提供精确的减法运算。
*
* @param v1 被减数
* @param v2 减数
* @return 两个参数的差
*/
public static double sub(double v1, double v2) {
java.math.BigDecimal b1 = new java.math.String(v1));
java.math.BigDecimal b2 = new java.math.String(v2));
return b1.subtract(b2).doubleValue();
}
public static double sub(String v1, String v2) {
java.math.BigDecimal b1 = new java.math.BigDecimal(v1);
java.math.BigDecimal b2 = new java.math.BigDecimal(v2);
return b1.subtract(b2).doubleValue();
}
/**
* 提供精确的乘法运算。
*
* @param v1
*      被乘数
* @param v2
*      乘数
* @return 两个参数的积
*/
public static double mul(double v1, double v2) {
java.math.BigDecimal b1 = new java.math.String(v1));
java.math.BigDecimal b2 = new java.math.String(v2));
return b1.multiply(b2).doubleValue();
}
public static double mul(String v1, String v2) {
java.math.BigDecimal b1 = new java.math.BigDecimal(v1);
java.math.BigDecimal b2 = new java.math.BigDecimal(v2);
return b1.multiply(b2).doubleValue();
}
/**
* 提供(相对)精确的除法运算,当发⽣除不尽的情况时,精确到⼩数点以后10位,以后的数字四舍五⼊。  *
* @param v1
*      被除数
* @param v2
*      除数
* @return 两个参数的商
*/
public static double div(double v1, double v2) {
return div(v1, v2, DEF_DIV_SCALE);
}
public static double div(String v1, String v2) {
java.math.BigDecimal b1 = new java.math.BigDecimal(v1);
java.math.BigDecimal b2 = new java.math.BigDecimal(v2);
return b1.divide(b2, DEF_DIV_SCALE, java.math.BigDecimal.ROUND_HALF_UP).doubleValue();
}
/**
* 提供(相对)精确的除法运算。当发⽣除不尽的情况时,由scale参数指定精度,以后的数字四舍五⼊。  *
* @param v1 被除数
* @param v2 除数
* @param scale 表⽰表⽰需要精确到⼩数点以后⼏位。
* @return 两个参数的商
*/
public static double div(double v1, double v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException("The  scale  must  be  a  positive  integer  or  zero");
}
java.math.BigDecimal b1 = new java.math.String(v1));
java.math.BigDecimal b2 = new java.math.String(v2));
return b1.divide(b2, scale, java.math.BigDecimal.ROUND_HALF_UP).doubleValue();
}
/**
* 提供精确的⼩数位四舍五⼊处理。
*
* @param v 需要四舍五⼊的数字
* @param scale ⼩数点后保留⼏位
* @return 四舍五⼊后的结果
*/
public static double round(double v, int scale) {
if (scale < 0) {
throw new IllegalArgumentException("The  scale  must  be  a  positive  integer  or  zero");
}
java.math.BigDecimal b = new java.math.String(v));
java.math.BigDecimal one = new java.math.BigDecimal("1");
return b.divide(one, scale, java.math.BigDecimal.ROUND_HALF_UP).doubleValue();
}
public static double round(String v, int scale) {
if (scale < 0) {
throw new IllegalArgumentException("The  scale  must  be  a  positive  integer  or  zero");
}
java.math.BigDecimal b = new java.math.BigDecimal(v);
java.math.BigDecimal one = new java.math.BigDecimal("1");
return b.divide(one, scale, java.math.BigDecimal.ROUND_HALF_UP).doubleValue();
}
}
使⽤时调⽤ Calculator 类的 conversion()⽅法,并传⼊算术表达式参数,即可返回⼀个 Double 类型的值。
使⽤⽰例:
public class MathTest {
public static void main(String[] args) {
String expression = "(0*1--3)-5/-4-(3*(-2.13))";
double result = version(expression);
System.out.println(expression + " = " + result);
System.out.println();
}
}
控制台输出:
(0*1--3)-5/-4-(3*(-2.13)) = 10.64
测试截图:
总结
以上就是本⽂关于Java计算数学表达式代码详解的全部内容,希望对⼤家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不⾜之处,欢迎留⾔指出。感谢朋友们对本站的⽀持!

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。