You need to calculate the result based on the configured expression (for example: 5+12* (3+5)/7.0), so use the stack in Java to implement the tool class in a way that uses a suffix expression.
The suffix expression is the way the operator is placed after the operand, for example: the suffix expression for the 3+2 suffix expression 32+,3* (2+1) is: 321+*, the solution to the expression evaluates the suffix expression based on the string expression first, and then uses the suffix expression and the operand stack to implement the calculation, The approximate idea of a calculation is to take an element from the suffix expression, and if the element is a numeric value then add to the operand stack, and if the operator takes two numbers from the operand stack to participate in the operation. The suffix expression is obtained with the help of two stacks, one is the suffix expression stack, one is the operation Fu Yi, the sequential scan arithmetic expression, if the value is directly added to the suffix expression stack, if the operator is using the current operator and the stack top elements in the operator stack to compare, If the current operator has a high priority, the current element enters the operation Fu Yi, if the current element has a low priority, then the Operation Fu Yi the top element out of the stack into the suffix expression stack, until the current element takes precedence over the top element of the operation Fu Yi the current element into the operation Fu Yi, currently only supports subtraction and parentheses operation.
Import java.util.Collections;
Import Java.util.Stack;
public class Calculator {
Private stack<string> Postfixstack = new stack<string> ();//suffix stack
Private stack<character> Opstack = new stack<character> ();//Operator stack
private int [] operatpriority = new int[] {0,3,2,1,-1,1,0,2};//operator precedence using operator ASCII-40 index
public static void Main (string[] args) {
System.out.println (5+12* (3+5)/7.0);
Calculator cal = new Calculator ();
String s = "5+12* (3+5)/7";
Double result = Cal.calculate (s);
SYSTEM.OUT.PRINTLN (result);
}
/**
* Calculated according to the given expression
* @param expression to evaluate for example: 5+12* (3+5)/7
* @return
*/
Public double Calculate (String expression) {
stack<string> resultstack = new stack<string> ();
Prepare (expression);
Collections.reverse (postfixstack);//reverse-suffix stack
String Firstvalue, secondvalue,currentvalue;//participates in the first value of the calculation, the second value and the arithmetic operator
while (!postfixstack.isempty ()) {
CurrentValue = Postfixstack.pop ();
if (!isoperator (Currentvalue.charat (0))) {//If no operator is stored in the operand stack
Resultstack.push (CurrentValue);
} else {//If an operator takes two values from the operand stack and participates in the operation with that number
SecondValue = Resultstack.pop ();
Firstvalue = Resultstack.pop ();
String Tempresult = Calculate (Firstvalue, SecondValue, Currentvalue.charat (0));
Resultstack.push (Tempresult);
}
}
Return double.valueof (Resultstack.pop ());
}
/**
* The data preparation phase converts expressions into suffix stacks
* @param expression
*/
private void Prepare (String expression) {
Opstack.push (', ');//operator put a comma at the bottom of the stack, this symbol has the lowest priority
char[] arr = Expression.tochararray ();
int currentindex = 0;//The position of the current character
int count = 0;//The length of the last arithmetic operator to the character of this arithmetic operator facilitates or between the values
Char Currentop, peekop;//current operator and stack top operator
for (int i=0;i<arr.length;i++) {
Currentop = Arr[i];
if (Isoperator (currentop)) {//If the current character is an operator
if (Count > 0) {
Postfixstack.push (New String (Arr,currentindex,count));//Take a number between two operators
}
Peekop = Opstack.peek ();
if (currentop = = ') ') {//encounters an inverse parenthesis removes the elements from the operator stack to the suffix stack until an opening parenthesis is encountered
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 ();
}
Opstack.push (Currentop);
}
Count = 0;
Currentindex = i+1;
} else {
count++;
}
}
if (Count > 1 | | | (count = = 1 &&!isoperator (Arr[currentindex]))) {//The last character is not parentheses or other operators are added in the suffix stack
Postfixstack.push (New String (Arr,currentindex,count));
}
while (Opstack.peek ()! = ', ') {
Postfixstack.push (String.valueof (Opstack.pop ()))//Add the remaining elements of the operation Ching to the suffix stack
}
}
/**
* Determine if it is an arithmetic symbol
* @param c
* @return
*/
Private Boolean Isoperator (char c) {
return c = = ' + ' | | c = = '-' | | c = = ' * ' | | c = = '/' | | c = = ' (' | | c = = ') ';
}
/**
* Use ASCII code-40 to do subscript arithmetic symbol priority
* @param cur
* @param Peek
* @return
*/
public boolean compare (char Cur,char peek) {//If Peek priority is higher than cur, return true, the default is Peek priority low
Boolean result = false;
if (operatpriority[(Peek) -40] >= operatpriority[(cur)-40]) {
result = true;
}
return result;
}
/**
* Calculated according to the given arithmetic operator
* @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;
}
}
public class Arithhelper {
Default division Operation Precision
private static final int def_div_scale = 16;
This class cannot be instantiated
Private Arithhelper () {
}
/**
* provides accurate addition operations.
*
* @param v1 Summand
* @param v2 Addend
* @return of two parameters and
*/
public static double Add (double v1, double v2) {
Java.math.BigDecimal B1 = new Java.math.BigDecimal (double.tostring (v1));
Java.math.BigDecimal b2 = new Java.math.BigDecimal (double.tostring (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 ();
}
/**
* Provides accurate subtraction operations.
*
* @param v1 minuend
* @param v2 meiosis
* @return The difference of two parameters
*/
public static double sub (double V1, double v2) {
Java.math.BigDecimal B1 = new Java.math.BigDecimal (double.tostring (v1));
Java.math.BigDecimal b2 = new Java.math.BigDecimal (double.tostring (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 ();
}
/**
* Provides accurate multiplication operations.
*
* @param v1
* by multiplier
* @param v2
* Multiplier
* @return The product of two parameters
*/
public static double Mul (double v1, double v2) {
Java.math.BigDecimal B1 = new Java.math.BigDecimal (double.tostring (v1));
Java.math.BigDecimal b2 = new Java.math.BigDecimal (double.tostring (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 ();
}
/**
* Provide (relative) accurate division operations, when there are no more than the case, accurate to 10 digits after the decimal point, after the number rounded.
*
* @param v1
* Dividend
* @param v2
* Divisor
* @return two parameters of the quotient
*/
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 ();
}
/**
* Provide (relative) accurate division operations. When an exception occurs, the precision is specified by the scale parameter, and the subsequent number is rounded.
*
* @param v1 Dividend
* @param v2 Divisor
* @param scale indicates the need to be accurate to several decimal places.
* @return two parameters of the quotient
*/
public static double div (double v1, double v2, int scale) {
if (Scale < 0) {
throw new IllegalArgumentException ("The scale must is a positive integer or zero");
}
Java.math.BigDecimal B1 = new Java.math.BigDecimal (double.tostring (v1));
Java.math.BigDecimal b2 = new Java.math.BigDecimal (double.tostring (v2));
Return B1.divide (B2, scale, Java.math.BigDecimal.ROUND_HALF_UP). Doublevalue ();
}
/**
* Provides precise rounding of decimal digits.
*
* @param v need to be rounded to the number
* Retain several @param scale decimal points
* Results after rounding @return
*/
public static double round (double V, int. scale) {
if (Scale < 0) {
throw new IllegalArgumentException ("The scale must is a positive integer or zero");
}
Java.math.BigDecimal B = New Java.math.BigDecimal (double.tostring (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 is 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 ();
}
}
Java implementation Arithmetic expression evaluation