请教一下大家,这道面试题的思路是什么?

qq_29448025 2017-04-21 08:25:05
...全文
524 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
liny_ 2017-04-27
  • 打赏
  • 举报
回复
ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName("JavaScript"); System.out.print(engine.eval("13+(5*6-20/4)"));
小灰狼 2017-04-25
  • 打赏
  • 举报
回复
引用 12 楼 emoheithree 的回复:
[quote=引用 11 楼 hemowolf 的回复:] [quote=引用 10 楼 emoheithree 的回复:] 用堆栈做。。。不过这个拿来面试也太麻烦了吧。。。 面试一般不都20~30行代码,这个少说也得40~50行。。。。。
题上要求是给思路,不是给代码 这个需求以前我就做过,基本思路就是中缀表达式转为后缀表达式,然后计算后缀表达式的值,当年的我程序是支持四则运算、括号,还支持单目的函数式运算,如 sin(2)、cos(4)等。[/quote] 你这个就跟麻烦了。。。。。 一般是中缀转成后缀,这其实可以看成是一个编译问题: 语法分析加上语义处理,你选择使用的语义处理方法为后缀表达式。[/quote] 这个是有点麻烦,不过这种处理思想目前已经很成熟了 因为当年有一个项目需求,有可能需要去分析算数表达式,所以自己写了一个分析器。 思路跟你说的差不多,就是中缀表达式先转为后缀表达式,用两个栈,一个栈存储操作数,一个栈存储操作符。中缀转后缀的过程是一个“编译”的过程,因为原始的中缀表达式可能是错误的,如果编译失败则直接报错。 原本是不打算用中缀转后缀的,但试了很多次都有无法解决的问题,最后发现还是转后缀现实
朔北冥 2017-04-25
  • 打赏
  • 举报
回复
引用 11 楼 hemowolf 的回复:
[quote=引用 10 楼 emoheithree 的回复:] 用堆栈做。。。不过这个拿来面试也太麻烦了吧。。。 面试一般不都20~30行代码,这个少说也得40~50行。。。。。
题上要求是给思路,不是给代码 这个需求以前我就做过,基本思路就是中缀表达式转为后缀表达式,然后计算后缀表达式的值,当年的我程序是支持四则运算、括号,还支持单目的函数式运算,如 sin(2)、cos(4)等。[/quote] 你这个就跟麻烦了。。。。。 一般是中缀转成后缀,这其实可以看成是一个编译问题: 语法分析加上语义处理,你选择使用的语义处理方法为后缀表达式。
小灰狼 2017-04-24
  • 打赏
  • 举报
回复
引用 10 楼 emoheithree 的回复:
用堆栈做。。。不过这个拿来面试也太麻烦了吧。。。 面试一般不都20~30行代码,这个少说也得40~50行。。。。。
题上要求是给思路,不是给代码 这个需求以前我就做过,基本思路就是中缀表达式转为后缀表达式,然后计算后缀表达式的值,当年的我程序是支持四则运算、括号,还支持单目的函数式运算,如 sin(2)、cos(4)等。
朔北冥 2017-04-23
  • 打赏
  • 举报
回复
用堆栈做。。。不过这个拿来面试也太麻烦了吧。。。 面试一般不都20~30行代码,这个少说也得40~50行。。。。。
qq_29448025 2017-04-23
  • 打赏
  • 举报
回复
引用 7 楼 weixin_38179324 的回复:
借鉴的别人的代码!!!!http://bbs.itheima.com/forum.php?mod=viewthread&tid=846&highlight= 范例1:Stack类。
package org.cxy.expression;

import java.util.*;
public class Stack<T> {
        private ArrayList<T> stack;
        /**
         *   功能:初始化堆栈。
         * */
        public Stack(){
                this.stack = new ArrayList<T>();
        }
        
        /**
         *   功能:查看栈顶元素。
         * */
        public T peek(){
                return this.stack.size()>0?this.stack.get(this.stack.size()-1):null;
        }
        
        /**
         *   功能:将元素压栈。
         * */
        public boolean push(T e){
                boolean mark = false;
                if(e != null){
                        this.stack.add(e);
                        mark = true;
                }
                return mark;
        }
        
        /**
         *   功能:将栈顶元素弹栈。
         * */
        public T pop(){
                T e = null;
                if(this.stack.size()>0){
                        e = this.stack.remove(this.stack.size()-1);
                }
                return e;
        }
        
        /**
         *   功能:判断栈是否为空。
         * */
        public boolean isEmpty(){
                return this.stack.size() == 0 ;
        }
        
        /**
         *   功能:返回栈内元素的个数。
         * */
        public int size(){
                return this.stack.size();
        }
        public String toString(){
                StringBuffer sub = new StringBuffer();
                sub.append("{");
                for(int i=0;i<this.stack.size();i++){
                        sub.append(this.stack.get(i));
                        sub.append(",");
                }
                sub.append("}");
                return sub.toString();
        }
}
范例2:ExpressionParser类。
package org.cxy.expression;

public class ExpressionParser {
        private Stack<Character> chStack; // 创建一个符号栈。
        private Stack<Double> numStack; // 创建一个数字栈。
        private StringBuffer expression;

        /**
         * 功能:初始化表达式。
         */
        public ExpressionParser(String expression) {
                this.expression = new StringBuffer(expression);
                this.chStack = new Stack<Character>();
                this.numStack = new Stack<Double>();
        }

        /**
         * 功能:计算表达式的值。
         */
        public double parse() throws Exception {
                // 若表达式还没有解析完。
                while (this.expression.length() > 0) {
                        // 获取当前表达式头部的第一个字符。
                        char ch = this.expression.charAt(0);
                        this.expression.deleteCharAt(0);
                        double num = 0;
                        boolean existNum = false;
                        // 若当前读取到的是数字。
                        while (ch >= '0' && ch <= '9') {
                                num = num * 10 + ch - '0';
                                existNum = true;
                                if (this.expression.length() > 0) {
                                        ch = this.expression.charAt(0);
                                        this.expression.deleteCharAt(0);
                                } else {
                                        break;
                                }
                        }
                        // 若刚刚解析完一个数字,则将数字压栈。
                        if (existNum) {
                                this.numStack.push(num);
                                //若整个表达式的解析已经结束了。
                                if(this.expression.length() == 0 && ch >= '0' && ch <= '9'){
                                        break;
                                }
                        }
                        // 若符号栈为空 或 栈顶元素为左括号 或 ch本身就是左括号,则直接将符号压入栈。
                        if (this.chStack.isEmpty() || this.chStack.peek() == '(' || ch == '(') {
                                this.chStack.push(ch);
                                continue;
                        }
                        switch (ch) {
                                case ')': {// 若当前符号是右括号,则不断的弹出一个运算符和两个操作数,直到遇到左括号为止。
                                        while (this.numStack.size() >= 2 && !this.chStack.isEmpty() && this.chStack.peek() != '(') {
                                                this.calc();
                                        }
                                        if (!this.chStack.isEmpty() && this.chStack.peek() == '(') {
                                                this.chStack.pop(); // 弹出这个左括号。
                                                continue;
                                        } else {
                                                throw new IllegalArgumentException("括号的数量不匹配!");
                                        }
                                }
                                case '*':
                                case '/':
                                case '%': {
                                        // 若符号栈栈顶元素为+、-、( 或者符号栈为空,则意味着符号栈栈顶符号比ch优先级底,所以,将ch压栈。否则,将符号栈栈顶元素弹出来,然后开始计算。
                                        while (this.numStack.size() >= 2 && !(this.chStack.isEmpty() || this.chStack.peek() == '(' || this.chStack.peek() == '+' || this.chStack.peek() == '-')) {
                                                this.calc();
                                        }
                                        // 若符号栈栈顶元素优先级比ch的低。
                                        if (this.chStack.isEmpty() || this.chStack.peek() == '(' || this.chStack.peek() == '+' || this.chStack.peek() == '-') {
                                                this.chStack.push(ch);
                                                continue;
                                        }
                                }
                                case '+':
                                case '-':{
                                        // 若当前符号栈栈顶元素不是(,符号栈也不为空,则将符号栈栈顶元素弹出来,然后开始计算。因为+、-号的优先级最低。
                                        while (this.numStack.size() >= 2 && (!this.chStack.isEmpty() || this.chStack.peek() != '(')) {
                                                this.calc();
                                        }
                                        if (this.chStack.isEmpty() || this.chStack.peek() == '(') {
                                                // 若符号栈栈顶元素为(、或符号栈为空,则将ch压栈。
                                                this.chStack.push(ch);
                                                continue;
                                        } else {
                                                throw new IllegalArgumentException("表达式格式不合法!");
                                        }
                                }
                                default : throw new IllegalArgumentException("运算符非法!");
                        }// switch 结束。
                }// while 结束。
                // 若符号栈不为空,则不断的从符号栈和数字栈中弹出元素,进行计算。
                while(!this.chStack.isEmpty()){
                        this.calc();
                }
                // 若最终数字栈中仅存一个元素,则证明表达式正确,栈顶元素就是表达式的值。
                return this.numStack.size() == 1 ? this.numStack.pop() : null;
        }

        /**
         * 功能:依据指定的操作数、运算符,进行运算。
         */
        private void calc() throws Exception {
                double b = this.numStack.pop();
                double a = this.numStack.pop();
                char op = this.chStack.pop();
                double result = 0;
                switch (op) {
                        case '+':        result = a + b;        break;
                        case '-':        result = a - b;        break;
                        case '*':        result = a * b;        break;
                        case '/': {
                                if (b == 0) {
                                        throw new ArithmeticException("除数不能为0!");
                                }
                                result = a / b;
                                break;
                        }
                        case '%': {
                                if (b == 0) {
                                        throw new ArithmeticException("除数不能为0!");
                                }
                                result = a % b;
                                break;
                        }
                }
                // 将运算的结果压栈。
                this.numStack.push(result);                
        }
        public void print(){
                System.out.println("数字栈元素:"+this.numStack);
                System.out.println("符号栈元素:"+this.chStack);
        }
}
范例3:Test类。
package org.cxy.expression;

public class Test {
        public static void main(String[] args){
//                String e = "65+403";   
//                String e = "65+403*4-125/25%4/3+4";
//                String e = "65+403*4)";
//                String e = "(65+403)*4-125/(25%4)/3+4";
//                String e = "((65+403)*4-125)/0/3+4";
                String e = "((65+403)*4-125/(25%4))/3+4";
                ExpressionParser ep = new ExpressionParser(e);
                try {
                        System.out.print("表达式 "+e+" 计算结果为:"+ep.parse());
                } catch (Exception e1) {
                        System.out.println("表达式解析时产生错误:"+e1.getMessage());
                        e1.printStackTrace();
                }
        }
}
// 第一个范例:表达式 65+403 计算结果为:468.0
// 第二个范例:表达式 65+403*4-125/25%4/3+4 计算结果为:1680.6666666666667
// 第三个范例:表达式解析时产生错误:括号的数量不匹配!
// 第四个范例:表达式 (65+403)*4-125/(25%4)/3+4 计算结果为:1834.3333333333333
// 第五个范例:表达式解析时产生错误:除数不能为0!
// 第六个范例:表达式 ((65+403)*4-125/(25%4))/3+4 计算结果为:586.3333333333334
希望能帮到您。 另外我更希望,您提的这个问题不是由于一时兴起,不然我感觉我这三个多小时(将近4个小时)的时间,花的不值得啊。 呜呜~ 我得歇会去了。
非常感谢你的回答,辛苦了。我问这个问题也真是想把它搞懂,免得以后面试又遇到相同的问题,今天好好来研究下。
Kevin_K2 2017-04-22
  • 打赏
  • 举报
回复
借鉴的别人的代码!!!!http://bbs.itheima.com/forum.php?mod=viewthread&tid=846&highlight= 范例1:Stack类。
package org.cxy.expression;

import java.util.*;
public class Stack<T> {
        private ArrayList<T> stack;
        /**
         *   功能:初始化堆栈。
         * */
        public Stack(){
                this.stack = new ArrayList<T>();
        }
        
        /**
         *   功能:查看栈顶元素。
         * */
        public T peek(){
                return this.stack.size()>0?this.stack.get(this.stack.size()-1):null;
        }
        
        /**
         *   功能:将元素压栈。
         * */
        public boolean push(T e){
                boolean mark = false;
                if(e != null){
                        this.stack.add(e);
                        mark = true;
                }
                return mark;
        }
        
        /**
         *   功能:将栈顶元素弹栈。
         * */
        public T pop(){
                T e = null;
                if(this.stack.size()>0){
                        e = this.stack.remove(this.stack.size()-1);
                }
                return e;
        }
        
        /**
         *   功能:判断栈是否为空。
         * */
        public boolean isEmpty(){
                return this.stack.size() == 0 ;
        }
        
        /**
         *   功能:返回栈内元素的个数。
         * */
        public int size(){
                return this.stack.size();
        }
        public String toString(){
                StringBuffer sub = new StringBuffer();
                sub.append("{");
                for(int i=0;i<this.stack.size();i++){
                        sub.append(this.stack.get(i));
                        sub.append(",");
                }
                sub.append("}");
                return sub.toString();
        }
}
范例2:ExpressionParser类。
package org.cxy.expression;

public class ExpressionParser {
        private Stack<Character> chStack; // 创建一个符号栈。
        private Stack<Double> numStack; // 创建一个数字栈。
        private StringBuffer expression;

        /**
         * 功能:初始化表达式。
         */
        public ExpressionParser(String expression) {
                this.expression = new StringBuffer(expression);
                this.chStack = new Stack<Character>();
                this.numStack = new Stack<Double>();
        }

        /**
         * 功能:计算表达式的值。
         */
        public double parse() throws Exception {
                // 若表达式还没有解析完。
                while (this.expression.length() > 0) {
                        // 获取当前表达式头部的第一个字符。
                        char ch = this.expression.charAt(0);
                        this.expression.deleteCharAt(0);
                        double num = 0;
                        boolean existNum = false;
                        // 若当前读取到的是数字。
                        while (ch >= '0' && ch <= '9') {
                                num = num * 10 + ch - '0';
                                existNum = true;
                                if (this.expression.length() > 0) {
                                        ch = this.expression.charAt(0);
                                        this.expression.deleteCharAt(0);
                                } else {
                                        break;
                                }
                        }
                        // 若刚刚解析完一个数字,则将数字压栈。
                        if (existNum) {
                                this.numStack.push(num);
                                //若整个表达式的解析已经结束了。
                                if(this.expression.length() == 0 && ch >= '0' && ch <= '9'){
                                        break;
                                }
                        }
                        // 若符号栈为空 或 栈顶元素为左括号 或 ch本身就是左括号,则直接将符号压入栈。
                        if (this.chStack.isEmpty() || this.chStack.peek() == '(' || ch == '(') {
                                this.chStack.push(ch);
                                continue;
                        }
                        switch (ch) {
                                case ')': {// 若当前符号是右括号,则不断的弹出一个运算符和两个操作数,直到遇到左括号为止。
                                        while (this.numStack.size() >= 2 && !this.chStack.isEmpty() && this.chStack.peek() != '(') {
                                                this.calc();
                                        }
                                        if (!this.chStack.isEmpty() && this.chStack.peek() == '(') {
                                                this.chStack.pop(); // 弹出这个左括号。
                                                continue;
                                        } else {
                                                throw new IllegalArgumentException("括号的数量不匹配!");
                                        }
                                }
                                case '*':
                                case '/':
                                case '%': {
                                        // 若符号栈栈顶元素为+、-、( 或者符号栈为空,则意味着符号栈栈顶符号比ch优先级底,所以,将ch压栈。否则,将符号栈栈顶元素弹出来,然后开始计算。
                                        while (this.numStack.size() >= 2 && !(this.chStack.isEmpty() || this.chStack.peek() == '(' || this.chStack.peek() == '+' || this.chStack.peek() == '-')) {
                                                this.calc();
                                        }
                                        // 若符号栈栈顶元素优先级比ch的低。
                                        if (this.chStack.isEmpty() || this.chStack.peek() == '(' || this.chStack.peek() == '+' || this.chStack.peek() == '-') {
                                                this.chStack.push(ch);
                                                continue;
                                        }
                                }
                                case '+':
                                case '-':{
                                        // 若当前符号栈栈顶元素不是(,符号栈也不为空,则将符号栈栈顶元素弹出来,然后开始计算。因为+、-号的优先级最低。
                                        while (this.numStack.size() >= 2 && (!this.chStack.isEmpty() || this.chStack.peek() != '(')) {
                                                this.calc();
                                        }
                                        if (this.chStack.isEmpty() || this.chStack.peek() == '(') {
                                                // 若符号栈栈顶元素为(、或符号栈为空,则将ch压栈。
                                                this.chStack.push(ch);
                                                continue;
                                        } else {
                                                throw new IllegalArgumentException("表达式格式不合法!");
                                        }
                                }
                                default : throw new IllegalArgumentException("运算符非法!");
                        }// switch 结束。
                }// while 结束。
                // 若符号栈不为空,则不断的从符号栈和数字栈中弹出元素,进行计算。
                while(!this.chStack.isEmpty()){
                        this.calc();
                }
                // 若最终数字栈中仅存一个元素,则证明表达式正确,栈顶元素就是表达式的值。
                return this.numStack.size() == 1 ? this.numStack.pop() : null;
        }

        /**
         * 功能:依据指定的操作数、运算符,进行运算。
         */
        private void calc() throws Exception {
                double b = this.numStack.pop();
                double a = this.numStack.pop();
                char op = this.chStack.pop();
                double result = 0;
                switch (op) {
                        case '+':        result = a + b;        break;
                        case '-':        result = a - b;        break;
                        case '*':        result = a * b;        break;
                        case '/': {
                                if (b == 0) {
                                        throw new ArithmeticException("除数不能为0!");
                                }
                                result = a / b;
                                break;
                        }
                        case '%': {
                                if (b == 0) {
                                        throw new ArithmeticException("除数不能为0!");
                                }
                                result = a % b;
                                break;
                        }
                }
                // 将运算的结果压栈。
                this.numStack.push(result);                
        }
        public void print(){
                System.out.println("数字栈元素:"+this.numStack);
                System.out.println("符号栈元素:"+this.chStack);
        }
}
范例3:Test类。
package org.cxy.expression;

public class Test {
        public static void main(String[] args){
//                String e = "65+403";   
//                String e = "65+403*4-125/25%4/3+4";
//                String e = "65+403*4)";
//                String e = "(65+403)*4-125/(25%4)/3+4";
//                String e = "((65+403)*4-125)/0/3+4";
                String e = "((65+403)*4-125/(25%4))/3+4";
                ExpressionParser ep = new ExpressionParser(e);
                try {
                        System.out.print("表达式 "+e+" 计算结果为:"+ep.parse());
                } catch (Exception e1) {
                        System.out.println("表达式解析时产生错误:"+e1.getMessage());
                        e1.printStackTrace();
                }
        }
}
// 第一个范例:表达式 65+403 计算结果为:468.0
// 第二个范例:表达式 65+403*4-125/25%4/3+4 计算结果为:1680.6666666666667
// 第三个范例:表达式解析时产生错误:括号的数量不匹配!
// 第四个范例:表达式 (65+403)*4-125/(25%4)/3+4 计算结果为:1834.3333333333333
// 第五个范例:表达式解析时产生错误:除数不能为0!
// 第六个范例:表达式 ((65+403)*4-125/(25%4))/3+4 计算结果为:586.3333333333334
希望能帮到您。 另外我更希望,您提的这个问题不是由于一时兴起,不然我感觉我这三个多小时(将近4个小时)的时间,花的不值得啊。 呜呜~ 我得歇会去了。
沁海棠 2017-04-22
  • 打赏
  • 举报
回复
public static void main(String[] args) throws Exception { ScriptEngineManager sem = new ScriptEngineManager(); //简单工厂模式方便扩展 ScriptEngine engine = sem.getEngineByName("js"); //存在这个引擎中,用java也可以获取 用js也可以获取 //put进去的key就相当于属性的名字 value就相当于属性的值 放进去的并不是 字符串 而是一条属性 engine.put("nihao", "456"); String str = "var user ={ name:'qin',age:18}; println(user.age)"; engine.eval(str); engine.eval("nihao = 789;"); //改变了nihao的值 engine.eval("println(nihao)"); //定义方法 通过eval执行 调用方法 engine.eval("function add(a,b){ var sum = a+b; return sum;}"); engine.eval("println(add(18,36))"); //通过java来获取属性 System.out.println(engine.get("nihao")); //当然用js可以求改nihao当然也可以获取 System.out.println("-----"); engine.eval("println(nihao)"); //engine 也实现了Invocable接口通过Invocable 调用js函数 Invocable invoke = (Invocable)engine; //指定函数名,指定数组,节后对象为Object Object obj = invoke.invokeFunction("add",new Object[]{9,6}); System.out.println(obj); //通过class获取的类加载器默认是在源文件路径也就是src下寻找文件的 URL url = EngineManage.class.getClassLoader().getResource("DynamicCompile/Rhino.js"); System.out.println(url.getPath()); FileReader f = new FileReader(url.getPath()); System.out.println(f); engine.eval(f); } public static void main(String[] args) throws ScriptException { ScriptEngineManager s = new ScriptEngineManager(); ScriptEngine engine = s.getEngineByName("js"); engine.eval("println(13+(5*6-20/4))"); } 小白自学有错误请大神指教
沁海棠 2017-04-22
  • 打赏
  • 举报
回复
貌似可以用js引擎直接用js算,具体忘了,去看看。
Scaarf 2017-04-22
  • 打赏
  • 举报
回复
围观大神回答
李德胜1995 2017-04-21
  • 打赏
  • 举报
回复
引用 1 楼 pany1209 的回复:
把字符串charAt转为List<String>,把中缀表达式转为后缀表达式,然后计算后缀表达式。。。
看看这个参考参考http://blog.csdn.net/yhhazr/article/details/7947962
李德胜1995 2017-04-21
  • 打赏
  • 举报
回复
引用 2 楼 qq_29448025 的回复:
[quote=引用 1 楼 pany1209 的回复:] 把字符串charAt转为List<String>,把中缀表达式转为后缀表达式,然后计算后缀表达式。。。
谢谢这么快就看到回答,请问能帮我简单写一个范例吗?[/quote] 以前遇见这种题,知道大概怎么解决而已。。。我去搜一下博客看看
qq_29448025 2017-04-21
  • 打赏
  • 举报
回复
引用 1 楼 pany1209 的回复:
把字符串charAt转为List<String>,把中缀表达式转为后缀表达式,然后计算后缀表达式。。。
谢谢这么快就看到回答,请问能帮我简单写一个范例吗?
李德胜1995 2017-04-21
  • 打赏
  • 举报
回复
把字符串charAt转为List<String>,把中缀表达式转为后缀表达式,然后计算后缀表达式。。。

62,628

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧