Java 将字符串求值为双精度(后缀表示法)
我想创建一个方法,用后缀符号解释这个列表(方法“words”将一个字符串拆分为一个单词列表,用\s分隔)。这就是我得到的,我想知道是否有一个较短的方法来解决这个问题,因为我经常在那里重复我自己Java 将字符串求值为双精度(后缀表示法),java,postfix-notation,Java,Postfix Notation,我想创建一个方法,用后缀符号解释这个列表(方法“words”将一个字符串拆分为一个单词列表,用\s分隔)。这就是我得到的,我想知道是否有一个较短的方法来解决这个问题,因为我经常在那里重复我自己 public static double eval(String expr) { return eval_(new ListStack<Double>() , words(expr)); } private static double eval_(St
public static double eval(String expr) {
return eval_(new ListStack<Double>() , words(expr));
}
private static double eval_(Stack<Double> s, List<String> expr) {
if (expr.isEmpty()) {
return s.top();
} else if (expr.head().equals("+")) {
Double fstValue = s.top();
s = s.pop();
Double sndValue = s.top();
s = s.pop();
s = s.push(add.apply(fstValue).apply(sndValue));
return eval_(s, expr.tail());
} else if (expr.head().equals("-")) {
Double fstValue = s.top();
s = s.pop();
Double sndValue = s.top();
s = s.pop();
s = s.push(sub.apply(fstValue).apply(sndValue));
return eval_(s, expr.tail());
} else if (expr.head().equals("*")) {
Double fstValue = s.top();
s = s.pop();
Double sndValue = s.top();
s = s.pop();
s = s.push(mul.apply(fstValue).apply(sndValue));
return eval_(s, expr.tail());
} else if (expr.head().equals("/")) {
Double fstValue = s.top();
s = s.pop();
Double sndValue = s.top();
s = s.pop();
s = s.push(div.apply(fstValue).apply(sndValue));
return eval_(s, expr.tail());
} else if (expr.head().equals("^")) {
Double fstValue = s.top();
s = s.pop();
Double sndValue = s.top();
s = s.pop();
s = s.push(pow.apply(fstValue).apply(sndValue));
return eval_(s, expr.tail());
} else if (expr.head().equals("!")) {
Double fstValue = s.top();
s = s.pop();
s = s.push(fact.apply(fstValue));
return eval_(s, expr.tail());
} else {
Double value = Double.parseDouble(expr.head());
s = s.push(value);
return eval_(s, expr.tail());
}
}
它总是抛出一个“NumberFormatException”。(可能是因为它无法将“+”解析为双精度)我做了什么
if
-else
语句替换为开关
-大小写
(我不必使用中断
,因为我返回
)else
-语句(如果已在if
-语句中返回,请不要使用它们)add
,sub
…替换???)private static double eval_(Stack <Double> s, List <String> expr) {
if (expr.isEmpty()) {
return s.top();
} else if (!expr.isEmpty()) {
switch (expr.head()) {
case "+":
return evalSingle(s, expr, add);
case "-":
return evalSingle(s, expr, sub);
case "*":
return evalSingle(s, expr, mul);
case "/":
return evalSingle(s, expr, div);
case "^":
return evalSingle(s, expr, pow);
case "!":
return evalSingle(s, expr, fact);
}
}
Double value = Double.parseDouble(expr.head());
s = s.push(value);
return eval_(s, expr.tail());
}
private static double evalSingle(Stack <Double> s, List <String> expr, ??? operator) {
Double fstValue = s.top();
s = s.pop();
Double sndValue = s.top();
s = s.pop();
s = s.push(operator == fact ? operator.apply(fstValue) : operator.apply(fstValue).apply(sndValue));
return eval_(s, expr.tail());
}
private static double eval(堆栈,列表expr){
if(expr.isEmpty()){
返回s.top();
}如果(!expr.isEmpty()){
开关(expr.head()){
格“+”:
返回evalSingle(s、expr、add);
案例“-”:
返回evalSingle(s、expr、sub);
案例“*”:
返回评估单(s、expr、mul);
案例“/:
返回evalSingle(s、expr、div);
案例“^”:
返回evalSingle(s、expr、pow);
案例“!”:
返回evalSingle(s、expr、fact);
}
}
Double value=Double.parseDouble(expr.head());
s=s.push(值);
返回eval_uS(expr.tail());
}
专用静态双evalSingle(堆栈、列表表达式、运算符){
双fstValue=s.top();
s=s.pop();
双SND值=s.top();
s=s.pop();
s=s.push(operator==fact?operator.apply(fstValue):operator.apply(fstValue).apply(sndValue));
返回eval_uS(expr.tail());
}
我认为你的教授是在开玩笑,但是是的,你把它缩短了(不是一行,除非你删除了所有LF)
只是解释一下,这是一个移位减少解析器的最小实现,当您有一个数字时,只需将其推送到堆栈(shift),当运算符用运算结果替换最上面的操作数时
请注意,这里我没有检查错误,因此不正确的表达式可能返回错误的值
import java.util.Stack;
public class PostFixEprParser {
public static double eval(String expr) {
Stack<Double> s=new Stack<>();
for (String token: expr.split("\\s+")) {
switch (token) {
case "+":
s.push(s.pop()+s.pop());
break;
case "-":
s.push(s.pop()-s.pop());
break;
case "*":
s.push(s.pop()*s.pop());
break;
case "/":
s.push(s.pop()/s.pop());
break;
case "^":
{
double exp=s.pop();
s.push(Math.pow(s.pop(), exp));
}
break;
case "!":
//TODO Here define your factorial function s.push(fact(s.pop()));
break;
default:
s.push(Double.valueOf(token));
}
}
return s.pop();
}
import java.util.Stack;
公共类后固定语法分析器{
公共静态双值(字符串表达式){
堆栈s=新堆栈();
用于(字符串标记:expr.split(\\s+)){
交换机(令牌){
格“+”:
s、 推(s.pop()+s.pop());
打破
案例“-”:
s、 推(s.pop()-s.pop());
打破
案例“*”:
s、 推(s.pop()*s.pop());
打破
案例“/:
s、 推(s.pop()/s.pop());
打破
案例“^”:
{
double exp=s.pop();
s、 push(Math.pow(s.pop(),exp));
}
打破
案例“!”:
//在这里定义阶乘函数s.push(fact(s.pop());
打破
违约:
s、 推送(Double.valueOf(token));
}
}
返回s.pop();
}
提供所需输入和输出的示例将非常有用。我发布了一个可能的解决方案,但您应该澄清您正在使用的一些方法(sum、add、mul、div、pow),这些方法是否已作为库或实现的一部分提供?请提供说明和签名。其他点“fact”应该有一个操作数,但您从堆栈中弹出两个值。我添加了一些函数,以便您可以看到它们的作用。感谢您帮我解决此问题!如果堆栈的行为不符合t如果是标准Java堆栈,那么您应该用一些相应的代码替换pop(),实现中的popTop()是什么?此外,如果您得到NumberFormatException,那么您的令牌既不是数字,也不是任何已定义的运算符,因此肯定是错误的输入。s.pop()返回堆栈,而不是单个变量(我们必须自己实现堆栈(和列表)。因此,我可能会在那里遇到问题。@Sentenza_IV所以我询问了自定义函数,因为这里我使用了Java标准堆栈实现,其中pop()返回一个元素。
private static double eval(String expr) {
switch (expr) {
case "+" -> s.push(add.apply(s.popTop().fst).apply(s.popTop().fst));
case "-" -> s.push(sub.apply(s.popTop().fst).apply(s.popTop().fst));
case "*" -> s.push(mul.apply(s.popTop().fst).apply(s.popTop().fst));
case "/" -> s.push(div.apply(s.popTop().fst).apply(s.popTop().fst));
case "^" -> {
double exp = s.popTop().fst;
s.push(Math.pow(s.popTop().fst, exp));
}
case "!" -> {
s.push(fact.apply(s.popTop().fst));
}
default -> s.push(Double.valueOf(String.valueOf(expr)));
}
return s.popTop().fst;
}
private static double eval_(Stack <Double> s, List <String> expr) {
if (expr.isEmpty()) {
return s.top();
} else if (!expr.isEmpty()) {
switch (expr.head()) {
case "+":
return evalSingle(s, expr, add);
case "-":
return evalSingle(s, expr, sub);
case "*":
return evalSingle(s, expr, mul);
case "/":
return evalSingle(s, expr, div);
case "^":
return evalSingle(s, expr, pow);
case "!":
return evalSingle(s, expr, fact);
}
}
Double value = Double.parseDouble(expr.head());
s = s.push(value);
return eval_(s, expr.tail());
}
private static double evalSingle(Stack <Double> s, List <String> expr, ??? operator) {
Double fstValue = s.top();
s = s.pop();
Double sndValue = s.top();
s = s.pop();
s = s.push(operator == fact ? operator.apply(fstValue) : operator.apply(fstValue).apply(sndValue));
return eval_(s, expr.tail());
}
import java.util.Stack;
public class PostFixEprParser {
public static double eval(String expr) {
Stack<Double> s=new Stack<>();
for (String token: expr.split("\\s+")) {
switch (token) {
case "+":
s.push(s.pop()+s.pop());
break;
case "-":
s.push(s.pop()-s.pop());
break;
case "*":
s.push(s.pop()*s.pop());
break;
case "/":
s.push(s.pop()/s.pop());
break;
case "^":
{
double exp=s.pop();
s.push(Math.pow(s.pop(), exp));
}
break;
case "!":
//TODO Here define your factorial function s.push(fact(s.pop()));
break;
default:
s.push(Double.valueOf(token));
}
}
return s.pop();
}