Java 表达式解析器和计算器 调车场算法

2023-12-09

所以任务是为表达式计算器创建我们自己的解析器。例如:

输入:3+2*1-6/3 输出:3

输入:3++2 输出:无效表达式

输入:-5+2 输出:-3

输入:5--2 输出:7

这里的代码解决了问题的一部分,除了它有一个固定的输入和负值无法解决,而且我还不太确定它是否真的解决了具有运算符优先级的表达式。 但我已经修改它以从用户那里获取输入表达式。 我几个小时以来一直想知道如何解决负值。帮助任何人吗?

请不要使用 JavaScript 引擎。

这是当前的代码

    import java.util.*; 

public class ExpressionParser   
{  
    // Associativity constants for operators  
    private static final int LEFT_ASSOC  = 0;  
    private static final int RIGHT_ASSOC = 1;  

    // Operators  
    private static final Map<String, int[]> OPERATORS = new HashMap<String, int[]>();  
    static   
    {  
        // Map<"token", []{precendence, associativity}>  
        OPERATORS.put("+", new int[] { 0, LEFT_ASSOC });  
        OPERATORS.put("-", new int[] { 0, LEFT_ASSOC });  
        OPERATORS.put("*", new int[] { 5, LEFT_ASSOC });  
        OPERATORS.put("/", new int[] { 5, LEFT_ASSOC });          
    }  

    // Test if token is an operator  
    private static boolean isOperator(String token)   
    {  
        return OPERATORS.containsKey(token);  
    }  

    // Test associativity of operator token  
    private static boolean isAssociative(String token, int type)   
    {  
        if (!isOperator(token))   
        {  
            throw new IllegalArgumentException("Invalid token: " + token);  
        }  

        if (OPERATORS.get(token)[1] == type) {  
            return true;  
        }  
        return false;  
    }  

    // Compare precedence of operators.      
    private static final int cmpPrecedence(String token1, String token2)   
    {  
        if (!isOperator(token1) || !isOperator(token2))   
        {  
            throw new IllegalArgumentException("Invalid tokens: " + token1  
                    + " " + token2);  
        }  
        return OPERATORS.get(token1)[0] - OPERATORS.get(token2)[0];  
    }  

    // Convert infix expression format into reverse Polish notation  
    public static String[] expToRPN(String[] inputTokens)   
    {  
        ArrayList<String> out = new ArrayList<String>();  
        Stack<String> stack = new Stack<String>();  

        // For each token  
        for (String token : inputTokens)   
        {  
            // If token is an operator  
            if (isOperator(token))   
            {    
                // While stack not empty AND stack top element   
                // is an operator  
                while (!stack.empty() && isOperator(stack.peek()))   
                {                      
                    if ((isAssociative(token, LEFT_ASSOC)         && 
                         cmpPrecedence(token, stack.peek()) <= 0) ||   
                        (isAssociative(token, RIGHT_ASSOC)        &&   
                         cmpPrecedence(token, stack.peek()) < 0))   
                    {  
                        out.add(stack.pop());     
                        continue;  
                    }  
                    break;  
                }
                // Push the new operator on the stack  
                stack.push(token);  
            }   
            // If token is a left bracket '('  
            else if (token.equals("("))   
            {  
                stack.push(token);  //   
            }   
            // If token is a right bracket ')'  
            else if (token.equals(")"))   
            {                  
                while (!stack.empty() && !stack.peek().equals("("))   
                {  
                    out.add(stack.pop());   
                }  
                stack.pop();   
            }   
            // If token is a number  
            else   
            {  
            //  if(!isOperator(stack.peek())){
            //      out.add(String.valueOf(token*10));
            //      }
                out.add(token);   
            }  
        }  
        while (!stack.empty())  
        {  
            out.add(stack.pop());   
        }  
        String[] output = new String[out.size()];  
        return out.toArray(output);  
    }  

    public static double RPNtoDouble(String[] tokens)  
    {          
        Stack<String> stack = new Stack<String>();  

        // For each token   
        for (String token : tokens) //for each   
        {  
            // If the token is a value push it onto the stack  
            if (!isOperator(token))   
            {  
                stack.push(token);                  
            }  
            else  
            {          
                // Token is an operator: pop top two entries  
                Double d2 = Double.valueOf( stack.pop() );  
                Double d1 = Double.valueOf( stack.pop() );  

                //Get the result  
                Double result = token.compareTo("*") == 0 ? d1 * d2 :   
                                token.compareTo("/") == 0 ? d1 / d2 :  
                                token.compareTo("+") == 0 ? d1 + d2 :  
                                                            d1 - d2;                 
              // Push result onto stack  
                stack.push( String.valueOf( result ));                                                  
            }                          
        }          

        return Double.valueOf(stack.pop());  
    }  

    public static void main(String[] args) throws Exception{  
        Scanner in = new Scanner(System.in);
        String reg = "((?<=[<=|>=|==|\\+|\\*|\\-|<|>|/|=])|(?=[<=|>=|==|\\+|\\*|\\-|<|>|/|=]))";
    while(true){
        try{
        System.out.println("Enter Your Expression");  
        //String[] input = "( 1 + 2 ) * ( 3 / 4 ) - ( 5 + 6 )".split(" ");
        String[] input =  in.nextLine() .split(reg);  
        String[] output = expToRPN(input);  

        // Build output RPN string minus the commas  
         System.out.print("Stack: ");
         for (String token : output) {  
                System.out.print("[ ");System.out.print(token + " "); System.out.print("]");
        }  
         System.out.println(" ");   
        // Feed the RPN string to RPNtoDouble to give result  
        Double result = RPNtoDouble( output );
        System.out.println("Answer= " + result);                
        }catch (NumberFormatException | EmptyStackException nfe){ 
            System.out.println("INVALID EXPRESSION"); }         
        }
    }
}  

更新的代码: 添加:unaryToexp() 函数。 我想做的是,每次出现“ - ”时,代码都会将其视为二进制文件,将其更改为“ _ ”作为另一个运算符,并且该运算符解决将事物乘以-1的问题(我首先想要的是添加 [- 1] 和 [*] 到 rpn 堆栈)。这里仍然有问题。

编译器说:

Enter Your Expression
-5+3
Stack: [  ][ 5 ][ - ][ 3 ][ + ]
Exception in thread "main" java.lang.NumberFormatException: empty String
        at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:10 11)
        at java.lang.Double.valueOf(Double.java:504)
        at ExpressionParser.RPNtoDouble(ExpressionParser.java:160)
        at ExpressionParser.main(ExpressionParser.java:194)* 

我认为这与Double d1 = Double.valueOf( stack.pop() );因为它仍然弹出另外两个值,我只需要一个来解决一元运算符。有什么帮助吗?

public class ExpressionParser   
{  
    // Associativity constants for operators  
    private static final int LEFT_ASSOC  = 0;  
    private static final int RIGHT_ASSOC = 1;  

    // Operators  
    private static final Map<String, int[]> OPERATORS = new HashMap<String, int[]>();  
    static   
    {  
       // Map<"token", []{precendence, associativity}>      
        OPERATORS.put("-", new int[] { 0, LEFT_ASSOC });  
        OPERATORS.put("+", new int[] { 0, LEFT_ASSOC });  
        OPERATORS.put("*", new int[] { 5, LEFT_ASSOC });  
        OPERATORS.put("/", new int[] { 5, LEFT_ASSOC });
        OPERATORS.put("_", new int[] { 5, RIGHT_ASSOC }); 
    }  

    // Test if token is an operator  
    private static boolean isOperator(String token)   
    {
        return OPERATORS.containsKey(token);  
    }  

    // Test associativity of operator token  
    private static boolean isAssociative(String token, int type)   
    {  
        if (!isOperator(token))   
        {  
            throw new IllegalArgumentException("Invalid token: " + token);  
        }  

        if (OPERATORS.get(token)[1] == type) {  
            return true;  
        }

        return false;  
    }  

    // Compare precedence of operators.      
    private static final int cmpPrecedence(String token1, String token2)   
    {  
        if (!isOperator(token1) || !isOperator(token2))   
        {  
            throw new IllegalArgumentException("Invalid tokens: " + token1  
                    + " " + token2);  
        }  
        return OPERATORS.get(token1)[0] - OPERATORS.get(token2)[0];  
    }  


    // CONVERT UNARY OPERATORS
    public static String[] unaryToexp(String[] inputTokens)
    {
        ArrayList<String> out = new ArrayList<String>();  
        Stack<String> stack = new Stack<String>(); 
                //if token is an unary minus
        for (String token : inputTokens)   
        {
                    if( ((token == "-") && (isOperator(stack.peek()) || stack.empty()  ))){  // 
                        token = "_";
                    }
                    else if (token == "-"){
                        token = "-";
                    }
            out.add(token);
             while (!stack.empty())  
                {  
                    out.add(stack.pop());
                }       
        }

        String[] output = new String[out.size()];  
        return out.toArray(output);  
    }

    // Convert infix expression format into reverse Polish notation  
    public static String[] expToRPN(String[] inputTokens)   
    {  
        ArrayList<String> out = new ArrayList<String>();  
        Stack<String> stack = new Stack<String>();  

        // For each token  
        for (String token : inputTokens)   
        { 
            // If token is an operator  
            if (isOperator(token))   
            {  
                // While stack not empty AND stack top element   
                // is an operator 

                while (!stack.empty() && isOperator(stack.peek()))
                {                      
                    if ((isAssociative(token, LEFT_ASSOC)         && 
                         cmpPrecedence(token, stack.peek()) <= 0) ||   
                        (isAssociative(token, RIGHT_ASSOC)        &&   
                         cmpPrecedence(token, stack.peek()) < 0))       

                    {  
                        out.add(stack.pop());     
                        continue; 
                    }
                    break;  
                }

                // Push the new operator on the stack 
                stack.push(token);  
            }
            // If token is a left bracket '('  
            else if (token.equals("("))   
            {  
                stack.push(token);  //   
            }   
            // If token is a right bracket ')'  
            else if (token.equals(")"))   
            {                  
                while (!stack.empty() && !stack.peek().equals("("))   
                {  
                    out.add(stack.pop());   
                }  
                stack.pop();   
            }   
            // If token is a number  
            else   
            {  
                out.add(token);   
            }  
        }  
        while (!stack.empty())  
        {  
            out.add(stack.pop());   
        }  
        String[] output = new String[out.size()];  
        return out.toArray(output);  
    }  

   public static double RPNtoDouble(String[] tokens)  
{          
    Stack<String> stack = new Stack<String>();  

    // For each token   
    for (String token : tokens)   
    {  
        // If the token is a value push it onto the stack  
        if (!isOperator(token))   
        {  
            stack.push(token);                  
        }  
        else  
        {  
            // Token is an operator: pop top two entries  
            Double d2 = Double.valueOf( stack.pop() );  
            Double d1 = Double.valueOf( stack.pop() );  

            //Get the result  
            Double result = token.compareTo("_") == 0 ? d2 * -1 :   
                            token.compareTo("*") == 0 ? d1 * d2 :   
                            token.compareTo("/") == 0 ? d1 / d2 :  
                            token.compareTo("+") == 0 ? d1 + d2 :  
                                                        d1 - d2;    

            // Push result onto stack  
            stack.push( String.valueOf( result ));                                                  
        }                          
    }          
    return Double.valueOf(stack.pop());  
}  

    public static void main(String[] args) throws Exception{  
        Scanner in = new Scanner(System.in);
        String reg = "((?<=[<=|>=|==|\\+|\\*|\\-|\\_|<|>|/|=])|(?=[<=|>=|==|\\+|\\*|\\-|<|>|/|=]))";
    while(true){
        //try{
        System.out.println("Enter Your Expression");  
        //String[] input = "( 1 + 2 ) * ( 3 / 4 ) - ( 5 + 6 )".split(" ");
        String[] input =  in.nextLine() .split(reg); 
        String[] unary = unaryToexp(input); //.split(reg);
        String[] output = expToRPN(unary);  

        // Build output RPN string minus the commas  
         System.out.print("Stack: ");
         for (String token : output) {  
                System.out.print("[ ");System.out.print(token); System.out.print(" ]");
        }  
         System.out.println(" ");   
        // Feed the RPN string to RPNtoDouble to give result  
        Double result = RPNtoDouble( output );
        System.out.println("Answer= " + result);                
        //}catch (){ 
            //System.out.println("INVALID EXPRESSION"); }           
        }
    }   
} 

给你:

private static final ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");

public static String eval(String matlab_expression){
    if(matlab_expression == null){
        return "NULL";
    }
    String js_parsable_expression = matlab_expression
            .replaceAll("\\((\\-?\\d+)\\)\\^(\\-?\\d+)", "(Math.pow($1,$2))")
            .replaceAll("(\\d+)\\^(\\-?\\d+)", "Math.pow($1,$2)");
    try{
        return engine.eval(js_parsable_expression).toString();
    }catch(javax.script.ScriptException e1){
        return null; // Invalid Expression
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java 表达式解析器和计算器 调车场算法 的相关文章

  • 在 JTable 中使用自定义 TablecellRenderer

    我是 Java 新手 我创建了一个JTable 就是这样addRow当我尝试向表中添加一行时 该方法有效 private void addTableRow String type String name String rank String
  • 我们可以在java中放弃已经签名的jar吗?

    I ve a jar文件具有旧签名 并希望使用新签名重新签名 是否可以 如果可能的话 怎么做 如果签名不是您拥有的 您需要先解压 jar 像这样 假设是unix 否则翻译成dos jar xvf JarName jar rm rf META
  • Java 8 中异常类型推断的一个独特功能

    在为该网站上的另一个答案编写代码时 我遇到了这个特性 static void testSneaky final Exception e new Exception sneakyThrow e no problems here nonSnea
  • 如何通过两跳 SSH 隧道使用 JProfiler

    我正在尝试将 JProfiler 连接到在我将调用的服务器上运行的 JVMremote 该服务器只能从我的工作站访问 local 通过我将调用的另一台服务器middle 我的计划是将 JProfiler 连接到remote是这样的 安装 J
  • Java JNDI 名称 java:/

    我正在遵循教程 https docs oracle com javase tutorial jndi index html https docs oracle com javase tutorial jndi index html 我的冒险
  • 打印数组时出错

    我得到这个代码 import java util import java io public class Oblig3A public static void main String args OrdAnalyse O new OrdAna
  • 从 java 类生成 xsd 的实用程序

    我想为以下类生成 xsd public class Node private String value private List
  • docker 中带有参数的 jar 文件

    Helo 我有一个 java jar 文件 当我从终端运行它时 它会接受一堆参数作为输入 我想制作一个 docker 映像并运行它 其中包含 jar 文件 我仍然可以在其中传递 jar 文件的参数 将 jar 文件设置为您的入口点 http
  • Logback 配置在单行上有异常吗?

    我的日志被提取 传输并合并到 elasticsearch 中 多行事件很难跟踪和诊断 有没有办法使用收集器和正则表达式将异常行分组到单个记录中登录配置 https logback qos ch manual layouts html xTh
  • SQLiteAssetHelper 甚至在从资产文件夹复制数据库之前就导致立即崩溃

    https github com jgilfelt android sqlite asset helper https github com jgilfelt android sqlite asset helper 我要从SQLiteOpe
  • SQLite 64位整数在jooq中被识别为int

    我有一个与 jOOQ 一起使用的 SQLite 数据库 当我使用 jOOQ 的代码生成工具时 它会按预期构建所有表和记录类 然而 所有的 SQLiteINTEGER列变成java lang Integer生成的代码中的字段 问题是 SQLi
  • 如何在 Java 中读取/转换 InputStream 为字符串?

    如果你有一个java io InputStream对象 您应该如何处理该对象并生成一个String 假设我有一个InputStream包含文本数据 我想将其转换为String 例如我可以将其写入日志文件 最简单的方法是什么InputStre
  • 如何将 .txt 文件的最后 5 行读入 java

    我有一个包含多个条目的文本文件 例如 hello there my name is JoeBloggs 我如何按降序阅读最后五个条目 即来自 JoeBloggs 那里 我目前有代码只能读取最后一行 public class TestLast
  • 如何在 iText 7 中创建页面大小不等的文档

    如何在 iText 7 中创建页面大小不等的文档 iText7 可以吗 在iText5中 我使用document setPageSize and document newPage 如果您通过高级 API 添加内容 Document add
  • 如何在 Spring GCP 中订阅多个 Google PubSub 项目?

    我想在 Spring Boot 应用程序中订阅多个 Google Cloud PubSub 项目 阅读完相关问题后如何使用 Spring Cloud 在一个 Spring Boot 应用程序中连接 配置两个 pubsub gcp 项目 ht
  • 如何强制 Spark 执行代码?

    我如何强制 Spark 执行对 map 的调用 即使它认为由于其惰性求值而不需要执行它 我试过把cache 与地图调用 但这仍然没有解决问题 我的地图方法实际上将结果上传到 HDFS 所以 它并非无用 但 Spark 认为它是无用的 简短回
  • 将Json字符串映射到java中的map或hashmap字段

    假设我从服务器返回了以下 JSON 字符串 response imageInstances one id 1 url ONE two id 2 url TWO 杰克逊代码大厦 JsonProperty 我怎样才能得到HashMap对象出来了
  • 每次修改代码时都必须 mvn clean install

    我不是来自 Java 世界 但我必须为我的一个项目深入研究它 我不明白为什么每次修改或更新代码时 都必须 mvn clean install 来调试代码的最新版本 你知道为什么吗 尝试按Ctrl Shift F9 热插拔 有时会有所帮助
  • 最新版本 6.* Struts2 支持 Tomcat 10 吗? [复制]

    这个问题在这里已经有答案了 最新版本 6 Struts2 支持 Tomcat 10 吗 异常启动过滤器 struts2 java lang ClassCastException class org apache struts2 dispat
  • Encog:BasicNetwork:无需预先构建数据集的在线学习

    我正在尝试使用 encog 库作为强化学习问题的函数逼近器 更准确地说 我正在尝试启动并运行多层感知器 BasicNetwork 由于我的代理将根据我选择的任何 RL 算法以某种方式探索世界 因此我无法预先构建任何 BasicNeuralD

随机推荐

  • CakePHP 3:带有缓存的 find()

    有关get 方法 我读过here 就像查找 get 集成了缓存 调用 get 时可以使用缓存选项来执行读缓存 但后来 在专门介绍find 方法 here 没有提到缓存 没有缓存的例子 cache支持的选项中未提及选项 所以我想知道 我可以使
  • 为什么 equal 运算符和 like 运算符之间的相等比较存在差异?

    SELECT au lname au fname FROM authors WHERE au lname Green au lname au fname Green Marjorie SELECT au lname au fname FRO
  • PHP PDO (MSSQL) 无法获取 OUTPUT 参数

    我正在尝试使用bindParam PHP PDO 获取输出 PHP PDO 库是 FreeTDS for MS SQL 驱动程序 无论我做什么 我似乎都无法按照 php net 上的建议在绑定参数中获得 输出 我已经验证我可以调用 EXEC
  • 在 ggplot 中对齐和排列图表

    我在 ggplot 中有两个图 在我想要对齐的轴上具有相似的范围 Using library grid grid newpage grid draw rbind ggplotGrob g1 ggplotGrob g2 size last w
  • angularJS cookie读取响应值

    如果我使用 http 在我的服务器上发出请求 我将得到以下响应 Request URL http www test tst login Request Method GET Status Code 200 OK Request Header
  • GROUP_CONCAT 编号

    是否可以在 GROUP CONCAT 中进行编号 like 如果 来自 GROUP CONCAT empnam SEPARATOR 我得到一套 lt JohnM DannyP TiffnyK KarlM gt 我需要有 lt 1 JohnM
  • PHP GD库在同一页面上输出图像和文本内容

    我试图将图像输出到浏览器 然后在同一页面上输出 HTML 与图像不直接相关 这可能吗 我花了很长时间才弄清楚 这是我一直在搞乱的代码
  • 自定义类上的 NSData?

    我即将研究 iPhone 上的蓝牙交互 现在 我读到唯一可以传输的对象是 NSData 对象 现在 我想转移我的 角色 对象 这个类看起来像这样 interface Character NSObject
  • C# 文件命名递增名称 001++

    我正在使用 C 创建一个小应用程序 我需要以递归方式命名文件 在创建文件名时递增文件名 我需要以下格式的文件名 alt 001 tmp alt 002 tmp 等 我总是看到 00 在递增的数字之前被删除 例如 001 然后返回 2 而不是
  • .NET MVC 自定义路由

    我想知道是否可以创建一个比控制器更高级别的路由映射 典型的路由将包括 controller action id 我正在寻找类似 section controller action id 或 controller section action
  • 如何拆分 ObservableCollection

    我有 ObservableCollection 有 100 条记录 现在我想将该集合拆分为 10 个新集合 每个新集合有 10 条记录 这意味着 1 个集合 100 条记录 10 个集合 10 条记录 1 个集合 任何帮助将不胜感激 使用
  • 常量函数指针

    我在函数指针方面遇到一些困难 我有一个基类 它定义了一个函数指针 通过typedef double function double x const 一个简单的问题 为什么上面的 typedef 不能编译 给出以下错误 错误 const 和
  • 展开循环有效,for 循环无效[重复]

    这个问题在这里已经有答案了 我有一些我不理解的行为 虽然展开的循环工作正常 循环抛出 IndexOutOfRangeExceptions 调试显示有 0 9 个 teamButtons 和 0 9 个卡片 c i private void
  • 为密度图中的平均值、数据框中的新变量创建 geom_vline,而不创建新表

    在这里我正在看mtcars数据集 我创建了一个密度图wt变量使用ggplot2包裹 我也把geom vline 图层添加一条垂直线作为平均值wt ggplot mtcars aes x wt geom density geom vline
  • 从 Uri 设置布局背景

    当我从图库中选择图像时 我会返回一个 Uri 我想将此图像设置为布局的背景 如果是ImageView就好了 我该怎么做 case LOAD FROM GALLERY mImageCaptureUri data getData ImageVi
  • Jenkins git-client:如何在 Windows 上迁移到 jgit

    自从詹金斯git client插件已移至使用jgit 配置方面存在很多问题 我见过的所有解决方案都涉及切换回使用旧的 git 命令行 因为现在大多数安装都已到位 以使其在大多数时间都可以工作 我们是同一条船 但是git命令行还是veryWi
  • jquery 工具 - 选项卡鼠标悬停 - 添加链接

    我喜欢这个工具 它可以在将鼠标移动到像素上时显示文本 http flowplayer org tools demos tabs mouseover htm 现在 当鼠标单击其中一个像素时 我尝试打开一个链接 我尝试了这样的方法 origin
  • 如何通过多项选择调整 Spinner 中项目的高度大小?

    我只是展示spinner在此基础上进行多项选择stackoverflow 答案 参见 Destil 答案 这里我的问题是我无法通过多项选择来调整 Spinner 中项目的高度大小 如何调整每个项目的高度 据我所知 您将必须使用自定义适配器
  • Visual Studio Express 2013 背后的代理

    我刚刚下载并安装了适用于 Windows 桌面的 Visual Studio Express 2013 我正在使用用户名 密码身份验证的代理后面工作 但我不知道如何注册该产品 女巫现在有效 14 天 每次 407 需要代理身份验证 我尝试编
  • Java 表达式解析器和计算器 调车场算法

    所以任务是为表达式计算器创建我们自己的解析器 例如 输入 3 2 1 6 3 输出 3 输入 3 2 输出 无效表达式 输入 5 2 输出 3 输入 5 2 输出 7 这里的代码解决了问题的一部分 除了它有一个固定的输入和负值无法解决 而且