2

https://stackoverflow.com/a/26227947/12698480

In this post, the Math expression calculation method is given by @Bruce.

I am pasting the code here, too:

public static double eval(final String str) {
return new Object() {
    int pos = -1, ch;

    void nextChar() {
        ch = (++pos < str.length()) ? str.charAt(pos) : -1;
    }

    boolean eat(int charToEat) {
        while (ch == ' ') nextChar();
        if (ch == charToEat) {
            nextChar();
            return true;
        }
        return false;
    }

    double parse() {
        nextChar();
        double x = parseExpression();
        if (pos < str.length()) throw new RuntimeException("Unexpected: " + (char)ch);
        return x;
    }

    // Grammar:
    // expression = term | expression `+` term | expression `-` term
    // term = factor | term `*` factor | term `/` factor
    // factor = `+` factor | `-` factor | `(` expression `)`
    //        | number | functionName factor | factor `^` factor

    double parseExpression() {
        double x = parseTerm();
        for (;;) {
            if      (eat('+')) x += parseTerm(); // addition
            else if (eat('-')) x -= parseTerm(); // subtraction
            else return x;
        }
    }

    double parseTerm() {
        double x = parseFactor();
        for (;;) {
            if      (eat('*')) x *= parseFactor(); // multiplication
            else if (eat('/')) x /= parseFactor(); // division
            else return x;
        }
    }

    double parseFactor() {
        if (eat('+')) return parseFactor(); // unary plus
        if (eat('-')) return -parseFactor(); // unary minus

        double x;
        int startPos = this.pos;
        if (eat('(')) { // parentheses
            x = parseExpression();
            eat(')');
        } else if ((ch >= '0' && ch <= '9') || ch == '.') { // numbers
            while ((ch >= '0' && ch <= '9') || ch == '.') nextChar();
            x = Double.parseDouble(str.substring(startPos, this.pos));
        } else if (ch >= 'a' && ch <= 'z') { // functions
            while (ch >= 'a' && ch <= 'z') nextChar();
            String func = str.substring(startPos, this.pos);
            x = parseFactor();
            if (func.equals("sqrt")) x = Math.sqrt(x);
            else if (func.equals("sin")) x = Math.sin(Math.toRadians(x));
            else if (func.equals("cos")) x = Math.cos(Math.toRadians(x));
            else if (func.equals("tan")) x = Math.tan(Math.toRadians(x));
            else throw new RuntimeException("Unknown function: " + func);
        } else {
            throw new RuntimeException("Unexpected: " + (char)ch);
        }

        if (eat('^')) x = Math.pow(x, parseFactor()); // exponentiation

        return x;
    }
}.parse();
}

Here, when I try to evaluate sin(30) for example, it gives the result as 0.49999999999994. Also the problem is with other trigonometric functions. For example, tan(45) result is 0.99999999999. Where is the problem?

One more issue, in Java Math library there is atan() function but not acot() function.

Any helps will be appreciated..

Anthon Santhez
  • 402
  • 1
  • 7
  • 13

2 Answers2

1

There is no problem with your code. It is working fine. Accurate trigonometric results cannot be calculated, so you get a close result. Now let's come to the second question. The functions related to sin, cos and tan are present in the library. Coses, sec and cot can be calculated using reciprocal. For example, cot-1 (x) can be calculated as tan-1 (1/x). Maybe, this is why they didn't bother creating a separate method for this.

Samudra Ganguly
  • 637
  • 4
  • 24
  • Thank you for expressing the second issue.. For the first issue, isn't there any way to calculate the accurate and exact result in trigonometry? Because the answer of _tan(45)_ is _1_ and it is not a rounded value, it is the exact value – Anthon Santhez Jun 20 '20 at 22:07
0

You are getting these results because all the trigonometric functions in Java expect radian parameters. You can convert angles to radians using the formula:

double angle = ...;
double radians = angle * Math.PI / 180;
ControlAltDel
  • 33,923
  • 10
  • 53
  • 80