我需要你的帮助,计算负数。 我不能考虑负数。 我无法只计算正数。 如果你帮我修理它,我会很高兴的。
我想确定 - 代码的复杂性是O(n)?
import java.util.Stack;
public class Q2_M3 // O(N)
{
public static double Calculate(String st)
{
char[] Arr = st.toCharArray();
Stack<Double> values = new Stack<Double>();// Stack for numbers:
Stack<Character> oper = new Stack<Character>();// Stack for Operators:
for (int i = 0; i < Arr.length; i++)
{
if (Arr[i] >= '0' && Arr[i] <= '9')
{
StringBuffer sbuf = new StringBuffer();
while ((i < Arr.length) && ((Arr[i] >= '0' && Arr[i] <= '9' )||(Arr[i] == '.')||(Arr[i] == '-')))
sbuf.append(Arr[i++]);
values.push( Double.parseDouble(sbuf.toString()));
i--;
}
// Current token is an opening brace, push it to 'oper'
else if (Arr[i] == '(')
oper.push(Arr[i]);
// Closing brace encountered, solve entire brace
else if (Arr[i] == ')')
{
while (oper.peek() != '(')
values.push(doArithmetic(oper.pop(), values.pop(), values.pop()));
oper.pop();
}
// Current token is an operator.
else if (Arr[i] == '+' || Arr[i] == '-' ||
Arr[i] == '*' || Arr[i] == '/')
{
// While top of 'oper' has same or greater precedence to current
// token, which is an operator. Apply operator on top of 'oper'
// to top two elements in values stack
while (!oper.empty() && hasPrecedence(Arr[i], oper.peek()))
values.push(doArithmetic(oper.pop(), values.pop(), values.pop()));
oper.push(Arr[i]);
}
}
// Entire expression has been parsed at this point, apply remaining
// oper to remaining values
double val= 0;
while (!oper.empty()){
if(!values.isEmpty())
//values.push(doArithmetic(oper.pop(), values.pop(), values.pop()));
values.push(doArithmetic(oper.pop(), values.pop(), values.pop()));
val=values.peek();
}
// Top of 'values' contains result, return it
return val;
}
// Returns true if 'op2' has higher or same precedence as 'op1',
// otherwise returns false.
public static boolean hasPrecedence(char op1, char op2)
{
if (op1 == '(' || op2 == '(' )
return false;
if ((op1 == '*' || op1 == '/') && (op2 == '+' || op2 == '-'))
return false;
else
return true;
}
public static double doArithmetic(char oper, Double x, Double y)
{
switch (oper)
{
case '+':
return y + x;
case '-':
return y - x;
case '*':
return y * x;
case '/':
if (x == 0)
System.out.println("Cannot divide by zero!");
else
return y / x;
}
return 0;
}
public static void main(String[] args)
{
String st = "-5*(6+2)-12/4";
String st2 = "20.2*(6.56567+2)-162/2";
System.out.println(Calculate(st));
System.out.println("Ans: "+Calculate(st2) );
}
}
答案 0 :(得分:1)
所以你需要区分二元运算符a-b
和一元运算符-c
。
就形式语法而言,您可以定义一个表达式,例如前缀是数字或 - 后跟数字
Expression :
PrefixExpression
Expression BinaryOp Expression
Prefix:
NumberOrVar
- NumberOrVar
( Expression )
NumberOrVar:
0-9
a-z
在代码中它变得像
Expression() {
while(more tokens) {
Prefix();
Char op = next input item, will be an operator
PushOperator(op)
Prefix()
}
}
Prefix() {
Char c = next input
if(c == '-') {
PushOperator(UnitaryMinus)
c = next input
}
if(c in 0-9 )
values.push(c)
}
答案 1 :(得分:0)
首先
while ((i < Arr.length) && ((Arr[i] >= '0' && Arr[i] <= '9' )||(Arr[i] == '.')||(Arr[i] == '-')))
只会因为您的情况看起来像这样
if ((Arr[i] >= '0' && Arr[i] <= '9') || Arr[i] == '-')
唯一改变的是右边的东西。
我还更改了函数的开头,以便在-
符号+-
的任何地方替换,除了开头。
import java.util.*;
public class f {
public static double Calculate(String st) {
String pattern = "-";
if (st.charAt(0)=='-')
st = '-'+st.substring(1).replaceAll(pattern, "+-");
else
st = st.replaceAll(pattern, "+-");
char[] Arr = st.toCharArray();
Stack<Double> values = new Stack<>();// Stack for numbers:
Stack<Character> oper = new Stack<>();// Stack for Operators:
for (int i = 0; i < Arr.length; i++) {
if ((Arr[i] >= '0' && Arr[i] <= '9') || Arr[i] == '-') {
StringBuffer sbuf = new StringBuffer();
while ((i < Arr.length) && ((Arr[i] >= '0' && Arr[i] <= '9' )||(Arr[i] == '.')||(Arr[i] == '-')))
sbuf.append(Arr[i++]);
values.push( Double.parseDouble(sbuf.toString()));
i--;
}
// Current token is an opening brace, push it to 'oper'
else if (Arr[i] == '(')
oper.push(Arr[i]);
// Closing brace encountered, solve entire brace
else if (Arr[i] == ')') {
while (oper.peek() != '(')
values.push(doArithmetic(oper.pop(), values.pop(), values.pop()));
oper.pop();
}
// Current token is an operator.
else if (Arr[i] == '+' || Arr[i] == '-' || Arr[i] == '*' || Arr[i] == '/') {
// While top of 'oper' has same or greater precedence to current
// token, which is an operator. Apply operator on top of 'oper'
// to top two elements in values stack
while (!oper.empty() && hasPrecedence(Arr[i], oper.peek()))
values.push(doArithmetic(oper.pop(), values.pop(), values.pop()));
oper.push(Arr[i]);
}
}
// Entire expression has been parsed at this point, apply remaining
// oper to remaining values
double val= 0;
while (!oper.empty()){
if(!values.isEmpty())
//values.push(doArithmetic(oper.pop(), values.pop(), values.pop()));
values.push(doArithmetic(oper.pop(), values.pop(), values.pop()));
val=values.peek();
}
// Top of 'values' contains result, return it
return val;
}
// Returns true if 'op2' has higher or same precedence as 'op1',
// otherwise returns false.
public static boolean hasPrecedence(char op1, char op2) {
if (op1 == '(' || op2 == '(' )
return false;
if ((op1 == '*' || op1 == '/') && (op2 == '+' || op2 == '-'))
return false;
else
return true;
}
public static double doArithmetic(char oper, Double x, Double y) {
switch (oper) {
case '+':
return y + x;
case '-':
return y - x;
case '*':
return y * x;
case '/':
if (x == 0)
System.out.println("Cannot divide by zero!");
else
return y / x;
}
return 0;
}
public static void main(String[] args) {
String st = "-5*(6+2)-12/4";
String st2 = "20.2*(6.56567+2)-162/2";
System.out.println(Calculate(st));
System.out.println("Ans: "+Calculate(st2) );
}
}
不确定这是否会使事情变得太慢,但它似乎适用于main方法中的测试用例。