有人可以解释这段代码是如何工作的吗? (StringBuffer & StringTokenizer)

Can someone explain how this code works? (StringBuffer & StringTokenizer)

我正在寻找如何计算数学表达式的方法,这些数学表达式可以使用 sin(90)10E8 等字符串计算输入,直到我看到这些我无法完全理解的代码这些作品。我想把这些作为基础,因为我想改进我的 MDAS 计算器。

我很难理解这些代码。我不熟悉 StringBufferStringTokenizerMath.ceilans += mul();( b.toString(), "\t" );,但我知道三角函数和 MDAS 运算的工作原理。

更新:我明白什么是StringTokenizer,但它与StringBuffer有什么关系?

import java.util.*;

public class Expression {

    String s, x;

    double term() {
        double ans = 0;
        StringBuffer temp = new StringBuffer();
        while (s.length() > 0 && Character.isDigit(s.charAt(0))) {
            temp.append(Integer.parseInt("" + s.charAt(0)));
            s = s.substring(1);
        }
        if (s.length() > 0 && s.charAt(0) == '.') {
            temp.append('.');
            s = s.substring(1);
            while (s.length() > 0 && Character.isDigit(s.charAt(0))) {
                temp.append(Integer.parseInt("" + s.charAt(0)));
                s = s.substring(1);
            }
        }
        if (s.length() > 0 && (s.charAt(0) == 'e' || s.charAt(0) == 'E')) {
            temp.append('e');
            s = s.substring(1);
            temp.append(s.charAt(0));
            s = s.substring(1);
            while (s.length() > 0 && Character.isDigit(s.charAt(0))) {
                temp.append(Integer.parseInt("" + s.charAt(0)));
                s = s.substring(1);
            }
        }
        ans = Double.valueOf(temp.toString()).doubleValue();
        return ans;
    }

    double paren() {
        double ans;
        if (s.charAt(0) == '(') {
            s = s.substring(1);
            ans = add();
            s = s.substring(1);
        } else {
            ans = term();
        }
        return ans;
    }

    double exp() {
        boolean neg = false;
        if (s.charAt(0) == '-') {
            neg = true;
            s = s.substring(1);
        }
        double ans = paren();
        while (s.length() > 0) {
            if (s.charAt(0) == '^') {
                s = s.substring(1);
                boolean expNeg = false;
                if (s.charAt(0) == '-') {
                    expNeg = true;
                    s = s.substring(1);
                }
                double e = paren();
                if (ans < 0) {
                    double x = 1;
                    if (Math.ceil(e) == e) {
                        if (expNeg)
                            e *= -1;
                        if (e == 0)
                            ans = 1;
                        else if (e > 0)
                            for (int i = 0; i < e; i++)
                                x *= ans;
                        else
                            for (int i = 0; i < -e; i++)
                                x /= ans;
                        ans = x;
                    } else {
                        ans = Math.log(-1);
                    }
                } else if (expNeg)
                    ans = Math.exp(-e * Math.log(ans));
                else
                    ans = Math.exp(e * Math.log(ans));
            } else
                break;
        }
        if (neg)
            ans *= -1;
        return ans;
    }

    double trig() {
        double ans = 0;
        boolean found = false;
        if (s.indexOf("sin") == 0) {
            s = s.substring(3);
            ans = Math.sin((trig() * Math.PI) / 180);
            found = true;
        } else if (s.indexOf("cos") == 0) {
            s = s.substring(3);
            ans = Math.cos((trig() * Math.PI) / 180);
            found = true;
        } else if (s.indexOf("tan") == 0) {
            s = s.substring(3);
            ans = Math.tan((trig() * Math.PI) / 180);
            found = true;
        }
        if (!found) {
            ans = exp();
        }
        return ans;
    }

    double mul() {
        double ans = trig();
        if (s.length() > 0) {
            while (s.length() > 0) {
                if (s.charAt(0) == '*') {
                    s = s.substring(1);
                    ans *= trig();
                } else if (s.charAt(0) == '/') {
                    s = s.substring(1);
                    ans /= trig();
                } else
                    break;
            }
        }
        return ans;
    }

    double add() {
        double ans = mul();
        while (s.length() > 0) {
            if (s.charAt(0) == '+') {
                s = s.substring(1);
                ans += mul();
            } else if (s.charAt(0) == '-') {
                s = s.substring(1);
                ans -= mul();
            } else {
                break;
            }
        }
        return ans;
    }

    public double evaluate() {
        s = x.intern();
        double last = add();
        return last;
    }

    public Expression(String s) {
        StringBuffer b = new StringBuffer();
        StringTokenizer t = new StringTokenizer(s, " ");
        while (t.hasMoreElements())
            b.append(t.nextToken());
        t = new StringTokenizer(b.toString(), "\t");
        b = new StringBuffer();
        while (t.hasMoreElements())
            b.append(t.nextToken());
        x = b.toString();
    }

    public String toString() {
        return x.intern();
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("Enter expression: ");
        Expression e = new Expression(sc.nextLine());
        System.out.println("\n" + e + " = " + e.evaluate() + "\n");
    }
}

http://docs.oracle.com/javase/7/docs/api/java/lang/StringBuffer.html

查看 StringBuffer 的 javadoc

请参阅 StringTokenizerat 的 javadoc http://docs.oracle.com/javase/7/docs/api/java/util/StringTokenizer.html

除了明显的台词,我会尝试对所有台词进行评论

import java.util.*;

public class Expression {

    String s, x;

    double term() {
        double ans = 0;
        StringBuffer temp = new StringBuffer(); //Efficient than simple String
        while (s.length() > 0 && Character.isDigit(s.charAt(0))) { //Check if the first character is a digit
            temp.append(Integer.parseInt("" + s.charAt(0))); //If true, add to temp String
            s = s.substring(1);
        }
        if (s.length() > 0 && s.charAt(0) == '.') {
            temp.append('.');
            s = s.substring(1);
            while (s.length() > 0 && Character.isDigit(s.charAt(0))) {
                temp.append(Integer.parseInt("" + s.charAt(0)));
                s = s.substring(1);
            }
        }
        if (s.length() > 0 && (s.charAt(0) == 'e' || s.charAt(0) == 'E')) {
            temp.append('e');
            s = s.substring(1);
            temp.append(s.charAt(0));
            s = s.substring(1);
            while (s.length() > 0 && Character.isDigit(s.charAt(0))) {
                temp.append(Integer.parseInt("" + s.charAt(0)));
                s = s.substring(1);
            }
        }
        ans = Double.valueOf(temp.toString()).doubleValue();
        return ans;
    }

    double paren() {
        double ans;
        if (s.charAt(0) == '(') {
            s = s.substring(1);
            ans = add();
            s = s.substring(1);
        } else {
            ans = term();
        }
        return ans;
    }

    double exp() {
        boolean neg = false;
        if (s.charAt(0) == '-') {
            neg = true;
            s = s.substring(1);
        }
        double ans = paren();
        while (s.length() > 0) {
            if (s.charAt(0) == '^') {
                s = s.substring(1);
                boolean expNeg = false;
                if (s.charAt(0) == '-') {
                    expNeg = true;
                    s = s.substring(1);
                }
                double e = paren();
                if (ans < 0) {
                    double x = 1;
                    if (Math.ceil(e) == e) { //Check Math.ceil documentation at http://docs.oracle.com/javase/7/docs/api/java/lang/Math.html#ceil(double)
                        if (expNeg)
                            e *= -1;
                        if (e == 0)
                            ans = 1;
                        else if (e > 0)
                            for (int i = 0; i < e; i++)
                                x *= ans;
                        else
                            for (int i = 0; i < -e; i++)
                                x /= ans;
                        ans = x;
                    } else {
                        ans = Math.log(-1); //http://docs.oracle.com/javase/7/docs/api/java/lang/Math.html#log(double)
                    }
                } else if (expNeg)
                    ans = Math.exp(-e * Math.log(ans));
                else
                    ans = Math.exp(e * Math.log(ans)); //http://docs.oracle.com/javase/7/docs/api/java/lang/Math.html#exp(double)
            } else
                break;
        }
        if (neg)
            ans *= -1;
        return ans;
    }

    double trig() {
        double ans = 0;
        boolean found = false;
        if (s.indexOf("sin") == 0) {
            s = s.substring(3);
            ans = Math.sin((trig() * Math.PI) / 180);
            found = true;
        } else if (s.indexOf("cos") == 0) {
            s = s.substring(3);
            ans = Math.cos((trig() * Math.PI) / 180);
            found = true;
        } else if (s.indexOf("tan") == 0) {
            s = s.substring(3);
            ans = Math.tan((trig() * Math.PI) / 180);
            found = true;
        }
        if (!found) {
            ans = exp();
        }
        return ans;
    }

    double mul() {
        double ans = trig();
        if (s.length() > 0) {
            while (s.length() > 0) {
                if (s.charAt(0) == '*') {
                    s = s.substring(1);
                    ans *= trig();
                } else if (s.charAt(0) == '/') {
                    s = s.substring(1);
                    ans /= trig();
                } else
                    break;
            }
        }
        return ans;
    }

    double add() {
        double ans = mul();
        while (s.length() > 0) {
            if (s.charAt(0) == '+') {
                s = s.substring(1);
                ans += mul();
            } else if (s.charAt(0) == '-') {
                s = s.substring(1);
                ans -= mul();
            } else {
                break;
            }
        }
        return ans;
    }

    public double evaluate() {
        s = x.intern();
        double last = add();
        return last;
    }

    public Expression(String s) {
        StringBuffer b = new StringBuffer();
        StringTokenizer t = new StringTokenizer(s, " "); //Creates a iterable t object so you can iterate over each "word" separate by space
        while (t.hasMoreElements())
            b.append(t.nextToken());
        t = new StringTokenizer(b.toString(), "\t");
        b = new StringBuffer();
        while (t.hasMoreElements())
            b.append(t.nextToken());
        x = b.toString();
    }

    public String toString() {
        return x.intern();
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("Enter expression: ");
        Expression e = new Expression(sc.nextLine());
        System.out.println("\n" + e + " = " + e.evaluate() + "\n");
    }
}

此程序通常读取数学表达式的字符串表示形式,然后解释和执行该表达式。至于你好奇的Java个元素:

StringBuffer 是一个更高效的操作 String 对象的接口。

StringTokenizer(String, String) 是 class 将字符串分解为标记。在此构造函数中,第一个参数是要分解为标记的字符串,第二个参数是用于创建这些标记的分隔符。

Math.ceil() returns 大于或等于参数且等于数学整数的最小(最接近负无穷大)双精度值。

StringBuffer.toString()写出一个String表示缓冲区中的数据

\t 是一个制表符

+=-=是{加/减}赋值运算符,将右操作数{加/减}到左操作数,并将结果赋值给左操作数。例如

int x = 0;
x += 2; // x is now 2