有人可以解释这段代码的工作原理吗(StringBuffer& StringTokenizer)

时间:2015-07-13 19:00:52

标签: java math calculator

我正在寻找如何计算数学表达式的方法,这些数学表达式可以使用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");
    }
}

2 个答案:

答案 0 :(得分:2)

该程序通常读取数学表达式的字符串表示,并解释和执行该表达式。至于您对以下内容感兴趣的Java元素:

StringBuffer是一个更有效的操作String对象的界面。

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

Math.ceil()返回大于或等于参数的最小(最接近负无穷大)double值,并且等于数学整数。

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

\t是一个标签

+=-=是{add / subtract}赋值运算符,它将右操作数{加/减}给左操作数并将结果赋给左操作数。 E.g。

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

答案 1 :(得分:1)

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

处的StringBuffer的javadoc

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

的javadoc

除了显而易见的行之外,我会尝试发表评论

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");
    }
}