1,105,328 Community Members

Did I do this right?

Member Avatar
seanbp
Junior Poster
129 posts since Jul 2010
Reputation Points: 4 [?]
Q&As Helped to Solve: 15 [?]
Skill Endorsements: 0 [?]
 
1
 

I read about a coding style where not one variable is changed. Everything must stay constant. I don't remember what it's called, but it's the bomb. I never realized this little project would be so easy.

Here is a 98 line calculator that supports ()^*/+-. If you find a bug, please don't hesitate to comment. It doesn't handle invalid input well and forgets to loop, keeping the code short. You'll get a bunch of debug output and the result should be after RESULT.

Now to the main question: Did I do this right?
Other questions: Could anything be better? Is there anything wrong with it?

package jcalculator;

import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        final String line = scanner.nextLine();
        System.out.println("RESULT: "+parentheses(line));
    }

    static String parentheses(final String arg)
    {
        System.out.println("parent: "+arg);
        if (arg.indexOf('(') < 0) return ""+math(arg);
        final int offset0 = arg.lastIndexOf("(");
        final int offset1 = next_of(offset0, arg, ')', +1);
        try {
            if (arg.charAt(offset0-1) != '*')
                return parentheses(arg.substring(0, offset0) +
                        "*" +
                        arg.substring(offset0));
        } catch (Exception e) {} // EOL
        try {
            if (arg.charAt(offset1+1) != '*')
                return parentheses(arg.substring(0, offset1+1) +
                        "*" +
                        arg.substring(offset1+1));
        } catch (Exception e) {} // EOL
        return parentheses(arg.substring(0, offset0) +
                math(arg.substring(offset0+1, offset1)) +
                arg.substring(offset1+1));
    }

    static int next_of(
            final int ret,
            final String string,
            final char find_char,
            final int increment)
    {
        if (string.charAt(ret) != find_char)
            return next_of(ret+increment, string, find_char, increment);
        else return ret;
    }

    static int last_integer(
            final int ret,
            final String string,
            final int increment)
    {
        try {
            if (string.charAt(ret) == '.') 
                return last_integer(ret+increment, string, increment);
            Integer.parseInt(""+string.charAt(ret));
            return last_integer(ret+increment, string, increment);
        } catch (Exception e) {
            return ret + -increment;
        }
    }

    static float math(final String arg) {
        System.out.println("math: "+arg);
        return Float.parseFloat(math_do(math_do(math_do(math_do(math_do( arg, 
                                '^'),   '*'),   '/'),   '+'),   '-'));
    }

    static String math_do(final String arg, char operator) {
        System.out.println("math_do: "+arg+" operator: "+operator);
        if (arg.indexOf(operator) < 0) return arg;
        else {
            int middle = arg.indexOf(operator);
            int left = last_integer(middle-1, arg, -1);
            int right = last_integer(middle+1, arg, +1);
            float a = Float.parseFloat(arg.substring(left, middle));
            float b = Float.parseFloat(arg.substring(middle+1, right+1));
            if (operator == '^') return math_do(arg.substring(0, left) +
                    Math.pow(a, b) +
                    arg.substring(right+1, arg.length()), operator);
            if (operator == '*') return math_do(arg.substring(0, left) +
                    (a*b) +
                    arg.substring(right+1, arg.length()), operator);
            if (operator == '/') return math_do(arg.substring(0, left) +
                    (a/b) +
                    arg.substring(right+1, arg.length()), operator);
            if (operator == '+') return math_do(arg.substring(0, left) +
                    (a+b) +
                    arg.substring(right+1, arg.length()), operator);
            if (operator == '-') return math_do(arg.substring(0, left) +
                    (a-b) +
                    arg.substring(right+1, arg.length()), operator);
            System.exit(1); // fatal
            return "";
        }
    }

}
Member Avatar
quuba
Posting Pro
573 posts since Nov 2008
Reputation Points: 81 [?]
Q&As Helped to Solve: 107 [?]
Skill Endorsements: 0 [?]
 
0
 

I like this!
2+2*2=6 OK (typical test for calculators)
-5+1 NO
-5 NO
5=5 OK
(-5)+1 NO
1+(-5) NO
+5 NO
Wrong work with the sign of number (+-) (distinction between the operator and the sign)
Program should show the first wrong positions in the input chain

Member Avatar
seanbp
Junior Poster
129 posts since Jul 2010
Reputation Points: 4 [?]
Q&As Helped to Solve: 15 [?]
Skill Endorsements: 0 [?]
 
0
 

I'll try error checking tomorrow.

I hope this works better (Negative number support):

package jcalculator;

import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        final String line = scanner.nextLine();
        System.out.println("RESULT: "+parentheses(line));
    }

    static String parentheses(final String arg)
    {
        System.out.println("parent: "+arg);
        if (arg.indexOf('(') < 0) return ""+math(arg);
        final int offset0 = arg.lastIndexOf("(");
        final int offset1 = next_of(offset0, arg, ')', +1);
        try {
            if (arg.charAt(offset0-1) != '*' &&
                    arg.charAt(offset0-1) != '^' &&
                    arg.charAt(offset0-1) != '*' &&
                    arg.charAt(offset0-1) != '/' &&
                    arg.charAt(offset0-1) != '+' &&
                    arg.charAt(offset0-1) != '-'
                    )
                return parentheses(arg.substring(0, offset0) +
                        "*" +
                        arg.substring(offset0));
        } catch (Exception e) {} // EOL
        try {
            if (arg.charAt(offset1+1) != '*' &&
                    arg.charAt(offset0-1) != '^' &&
                    arg.charAt(offset0-1) != '*' &&
                    arg.charAt(offset0-1) != '/' &&
                    arg.charAt(offset0-1) != '+' &&
                    arg.charAt(offset0-1) != '-'
                    )
                return parentheses(arg.substring(0, offset1+1) +
                        "*" +
                        arg.substring(offset1+1));
        } catch (Exception e) {} // EOL
        return parentheses(arg.substring(0, offset0) +
                math(arg.substring(offset0+1, offset1)) +
                arg.substring(offset1+1));
    }

    static int next_of(
            final int ret,
            final String string,
            final char find_char,
            final int increment)
    {
        if (string.charAt(ret) != find_char)
            return next_of(ret+increment, string, find_char, increment);
        else return ret;
    }

    static int last_integer(
            final int ret,
            final String string,
            final int increment)
    {
        try {
            if (string.charAt(ret) == '.')
                return last_integer(ret+increment, string, increment);
            if (string.charAt(ret) == '-' && increment < 0)
                return ret;
            if (string.charAt(ret) == '-' && increment > 0)
                return last_integer(ret+increment, string, increment);
            Integer.parseInt(""+string.charAt(ret));
            return last_integer(ret+increment, string, increment);
        } catch (Exception e) {
            return ret + -increment;
        }
    }

    static float math(final String arg) {
        System.out.println("math: "+arg);
        return Float.parseFloat(math_do(math_do(math_do(math_do(math_do( arg,
                                '^'),   '*'),   '/'),   '+'),   '-'));
    }

    static String math_do(final String arg, char operator) {
        System.out.println("math_do: "+arg+" operator: "+operator);
        if (arg.indexOf(operator) < 1) return arg;
        else {
            final int middle = arg.indexOf(operator);
            final int left = last_integer(middle-1, arg, -1);
            final int right = last_integer(middle+1, arg, +1);
            final String a_sz = arg.substring(left, middle);
            final String b_sz = arg.substring(middle+1, right+1);
            if (a_sz.length() == 0 || b_sz.length() == 0) return arg;
            final float a = Float.parseFloat(a_sz);
            final float b = Float.parseFloat(b_sz);
            if (operator == '^') return math_do(arg.substring(0, left) +
                    Math.pow(a, b) +
                    arg.substring(right+1, arg.length()), operator);
            if (operator == '*') return math_do(arg.substring(0, left) +
                    (a*b) +
                    arg.substring(right+1, arg.length()), operator);
            if (operator == '/') return math_do(arg.substring(0, left) +
                    (a/b) +
                    arg.substring(right+1, arg.length()), operator);
            if (operator == '+') return math_do(arg.substring(0, left) +
                    (a+b) +
                    arg.substring(right+1, arg.length()), operator);
            if (operator == '-') return math_do(arg.substring(0, left) +
                    (a-b) +
                    arg.substring(right+1, arg.length()), operator);
            System.exit(1); // fatal
            return "";
        }
    }

}
Member Avatar
seanbp
Junior Poster
129 posts since Jul 2010
Reputation Points: 4 [?]
Q&As Helped to Solve: 15 [?]
Skill Endorsements: 0 [?]
 
0
 

Nope. Still buggy.

Member Avatar
quuba
Posting Pro
573 posts since Nov 2008
Reputation Points: 81 [?]
Q&As Helped to Solve: 107 [?]
Skill Endorsements: 0 [?]
 
0
 

Maybe in the first phase, enter additional characters to the alphabet, for example, N and P, which means unary operators, and treat them in a similar way as other +=*/
N5 =- 5
P5 = 5
N, P have the highest operator precedence
Operator Precedence: http://download.oracle.com/javase/tutorial/java/nutsandbolts/operators.html

Your parser is fantastic. Perfect for breaking the head (for long time?)

Member Avatar
seanbp
Junior Poster
129 posts since Jul 2010
Reputation Points: 4 [?]
Q&As Helped to Solve: 15 [?]
Skill Endorsements: 0 [?]
 
0
 

OK, I beat my head on the keyboard and this came out:

package jcalculator;

import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        final String line = scanner.nextLine();
        System.out.println("RESULT: "+parentheses(line));
    }

    static String parentheses(final String arg)
    {
        if (arg.indexOf('(') < 0) return ""+math(arg);
        final int offset0 = arg.indexOf("(");
        final int offset1 = next_of(offset0, arg, ')', +1);
        try {
            if (arg.charAt(offset0-1) != '*' &&
                    arg.charAt(offset0-1) != '^' &&
                    arg.charAt(offset0-1) != '/' &&
                    arg.charAt(offset0-1) != '+'
                    )
                return parentheses(arg.substring(0, offset0) +
                        "*" +
                        arg.substring(offset0));
        } catch (Exception e) {} // EOL
        try {
            if (arg.charAt(offset1+1) != '*' &&
                    arg.charAt(offset0+1) != '^' &&
                    arg.charAt(offset0+1) != '/' &&
                    arg.charAt(offset0+1) != '+'
                    )
                return parentheses(arg.substring(0, offset1+1) +
                        "*" +
                        arg.substring(offset1+1));
        } catch (Exception e) {} // EOL
        return parentheses(arg.substring(0, offset0) +
                math(arg.substring(offset0+1, offset1)) +
                arg.substring(offset1+1));
    }

    static int next_of(
            final int ret,
            final String string,
            final char find_char,
            final int increment)
    {
        if (string.charAt(ret) != find_char)
            return next_of(ret+increment, string, find_char, increment);
        else return ret;
    }

    static int last_integer(
            final int ret,
            final String string,
            final int increment,
            final boolean first_char)
    {
        try {
            if (string.charAt(ret) == '.')
                return last_integer(ret+increment, string, increment, false);
            if (string.charAt(ret) == '-' && first_char && increment > 0)
                return last_integer(ret+increment, string, increment, false);
            Integer.parseInt(""+string.charAt(ret));
            if (ret == 1) return 0;
            return last_integer(ret+increment, string, increment, false);
        } catch (Exception e) {
            return ret+-increment;
        }
    }

    static float math(final String arg) {
        String result = math_do(math_do(math_do(math_do(math_do( arg,
                                '^'),   '*'),   '/'),   '+'),   '-');
        try {if (result.charAt(0) == result.charAt(1))
            return Float.parseFloat(result.substring(1)); }
        catch (Exception e) {} // string too short?
        return Float.parseFloat(result);
    }

    static String math_do(final String arg, char operator) {
        if (arg.indexOf(operator, 1) < 0) return arg;
        else {
            final int middle = arg.indexOf(operator, 1);
            final int left = last_integer(middle-1, arg, -1, true);
            final int right = last_integer(middle+1, arg, +1, true);
            final String a_sz = arg.substring(left, middle);
            final String b_sz = arg.substring(middle+1, right+1);
            if (a_sz.length() == 0 || b_sz.length() == 0) return arg;
            final float a = Float.parseFloat(a_sz);
            final float b = Float.parseFloat(b_sz);
            if (operator == '^') return math_do(arg.substring(0, left) +
                    Math.pow(a, b) +
                    arg.substring(right+1, arg.length()), operator);
            if (operator == '*') return math_do(arg.substring(0, left) +
                    (a*b) +
                    arg.substring(right+1, arg.length()), operator);
            if (operator == '/') return math_do(arg.substring(0, left) +
                    (a/b) +
                    arg.substring(right+1, arg.length()), operator);
            if (operator == '+') return math_do(arg.substring(0, left) +
                    (a+b) +
                    arg.substring(right+1, arg.length()), operator);
            if (operator == '-') return math_do(arg.substring(0, left) +
                    (a-b) +
                    arg.substring(right+1, arg.length()), operator);
            System.exit(1); // fatal
            return "";
        }
    }

}
Member Avatar
quuba
Posting Pro
573 posts since Nov 2008
Reputation Points: 81 [?]
Q&As Helped to Solve: 107 [?]
Skill Endorsements: 0 [?]
 
0
 

Protect your head.
Before the destruction of the keyboard, look at this

tests:
-5-2
RESULT: -7.0 OK
-3+5
RESULT: 2.0 OK
-0-0
RESULT: -0.0 OK?
2--2
RESULT: 4.0 OK!
--2
RESULT: -2.0 NO
---3
Exception in thread "main" java.lang.NumberFormatException: For input string: "---3"

Member Avatar
quuba
Posting Pro
573 posts since Nov 2008
Reputation Points: 81 [?]
Q&As Helped to Solve: 107 [?]
Skill Endorsements: 0 [?]
 
0
 

I read about a coding style where not one variable is changed. Everything must stay constant. I don't remember what it's called, but it's the bomb.

This style is a FUNCTIONAL PROGRAMMING. Clojure etc.

Member Avatar
seanbp
Junior Poster
129 posts since Jul 2010
Reputation Points: 4 [?]
Q&As Helped to Solve: 15 [?]
Skill Endorsements: 0 [?]
 
0
 

Here is today's version. Much improvement parsing parentheses.

package jcalculator;

import java.util.Scanner;

public class Main {

    static final Scanner scanner = new Scanner(System.in);

    public static void main(String[] args) {
        try {
            final String line = scanner.nextLine();
            System.out.println("RESULT: "+parentheses(line));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    static String parentheses(final String arg) throws Exception
    {
        if (arg.indexOf('(') < 0) return ""+math(arg);
        final int offset0 = deepest_parent(arg, 0, 0);
        final int offset1 = arg.indexOf(')', offset0);
        try {
            if (arg.charAt(offset0-1) != '*' &&
                    arg.charAt(offset0-1) != '^' &&
                    arg.charAt(offset0-1) != '/' &&
                    arg.charAt(offset0-1) != '+'
                    )
                return parentheses(arg.substring(0, offset0) +
                        "*" +
                        arg.substring(offset0));
        } catch (Exception e) {} // EOL
        try {
            if (arg.charAt(offset1+1) != '*' &&
                    arg.charAt(offset0+1) != '^' &&
                    arg.charAt(offset0+1) != '/' &&
                    arg.charAt(offset0+1) != '+'
                    )
                return parentheses(arg.substring(0, offset1+1) +
                        "*" +
                        arg.substring(offset1+1));
        } catch (Exception e) {} // EOL
        return parentheses(arg.substring(0, offset0) +
                math(arg.substring(offset0+1, offset1)) +
                arg.substring(offset1+1));
    }

    static int deepest_parent(String string, int offset1, int offset2) {
        if (string.charAt(offset1) != '(')
            return deepest_parent(string, offset1+1, offset1+1);
        else {
            if (string.charAt(offset2) == '(')
                return deepest_parent(string, offset2, offset2+1);
            if (string.charAt(offset2) == ')')
                return offset1;
            return deepest_parent(string, offset1, offset2+1);
        }
    }

    static int last_integer(
            final int ret,
            final String string,
            final int increment,
            final boolean first_char)
    {
        try {
            if (string.charAt(ret) == '.' || string.charAt(ret) == 'E')
                return last_integer(ret+increment, string, increment, false);
            if (string.charAt(ret) == '-' && first_char && increment > 0)
                return last_integer(ret+increment, string, increment, false);
            Integer.parseInt(""+string.charAt(ret));
            if (ret == 1) return 0;
            return last_integer(ret+increment, string, increment, false);
        } catch (Exception e) {
            return ret+-increment;
        }
    }

    static float math(final String arg) throws Exception {
        String result = math_do(math_do(math_do(math_do(math_do( arg,
                        '^'),   '*'),   '/'),   '+'),   '-');
        return Float.parseFloat(extra_operators(result));
    }

    static String extra_operators(final String string) throws Exception {
        try {
            final boolean is_same = string.charAt(0) == string.charAt(1);
            final boolean is_operator =
                    string.charAt(0) == '-' || string.charAt(0) == '+';
            if (is_same && is_operator) {
                return extra_operators(string.substring(2));
            }
        } catch (Exception e) {
        }
        return string;
    }

    static String math_do(final String arg, char operator) throws Exception {
        if (arg.indexOf(operator, 1) < 0) return arg;
        else {
            final int middle = arg.indexOf(operator, 1);
            final int left = last_integer(middle-1, arg, -1, true);
            final int right = last_integer(middle+1, arg, +1, true);
            final String a_sz = arg.substring(left, middle);
            final String b_sz = arg.substring(middle+1, right+1);
            if (a_sz.length() == 0 || b_sz.length() == 0) return arg;
            final float a = Float.parseFloat(a_sz);
            final float b = Float.parseFloat(b_sz);
            if (operator == '^') return math_do(arg.substring(0, left) +
                    Math.pow(a, b) +
                    arg.substring(right+1, arg.length()), operator);
            if (operator == '*') return math_do(arg.substring(0, left) +
                    (a*b) +
                    arg.substring(right+1, arg.length()), operator);
            if (operator == '/') return math_do(arg.substring(0, left) +
                    (a/b) +
                    arg.substring(right+1, arg.length()), operator);
            if (operator == '+') return math_do(arg.substring(0, left) +
                    (a+b) +
                    arg.substring(right+1, arg.length()), operator);
            if (operator == '-') return math_do(arg.substring(0, left) +
                    (a-b) +
                    arg.substring(right+1, arg.length()), operator);
            System.exit(1); // fatal
            return "";
        }
    }

}
Member Avatar
quuba
Posting Pro
573 posts since Nov 2008
Reputation Points: 81 [?]
Q&As Helped to Solve: 107 [?]
Skill Endorsements: 0 [?]
 
1
 

the result of 1.0/2500.0 is worrying!
seanbp, have you patience?

run:
2E10+1
RESULT: 2.0E10
2E2+1
RESULT: 201.0
2E2^2
RESULT: 40000.0
2E2^-2
java.lang.NumberFormatException: For input string: "2.5E"
run:
2^2
RESULT: 4.0
-2^2
RESULT: 4.0
-2^3
RESULT: -8.0
-2^(2)
RESULT: 4.0
-2^(-2)
RESULT: 0.25
-2^-2
RESULT: 0.25
2E2^(-2)
java.lang.NumberFormatException: For input string: "2.5E"
run:
2E2
RESULT: 200.0
200^2
RESULT: 40000.0
200^-2
java.lang.NumberFormatException: For input string: "2.5E"
run:
200^(-2)
java.lang.NumberFormatException: For input string: "2.5E"
* run:
20^(-2)
RESULT: 0.0025
30^-2
RESULT: 0.0011111111
9^9^9
RESULT: Infinity
100^-2
java.lang.NumberFormatException: For input string: "1.0E"
50^-2
java.lang.NumberFormatException: For input string: "4.0E"
1/50^2
java.lang.NumberFormatException: For input string: "4.0E"
run:
50^2
RESULT: 2500.0
1/2500.0
java.lang.NumberFormatException: For input string: "4.0E"
run:
1.0/2500.0
java.lang.NumberFormatException: For input string: "4.0E"

Member Avatar
seanbp
Junior Poster
129 posts since Jul 2010
Reputation Points: 4 [?]
Q&As Helped to Solve: 15 [?]
Skill Endorsements: 0 [?]
 
0
 

quuba,
Try this. You've been a great help. This project would be going nowhere without you. :)

Note: 9^9^9 no longer Infinity.

package jcalculator;

import java.util.Scanner;

public class Main {

    static final Scanner scanner = new Scanner(System.in);

    public static void main(
            String[] args)
    {
        try {
            final String line = scanner.nextLine();
            System.out.println("RESULT: "+parentheses(line));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    static String parentheses(
            final String arg)
            throws Exception
    {
        if (arg.indexOf('(') < 0) return ""+math(arg);
        final int offset0 = deepest_parent(arg, 0, 0);
        final int offset1 = arg.indexOf(')', offset0);
        try {
            if (arg.charAt(offset0-1) != '*' &&
                    arg.charAt(offset0-1) != '^' &&
                    arg.charAt(offset0-1) != '/' &&
                    arg.charAt(offset0-1) != '+' &&
                    arg.charAt(offset0-1) != '-'
                    )
                return parentheses(arg.substring(0, offset0) +
                        "*" +
                        arg.substring(offset0));
        } catch (Exception e) {} // EOL
        try {
            if (arg.charAt(offset1+1) != '*' &&
                    arg.charAt(offset0+1) != '^' &&
                    arg.charAt(offset0+1) != '/' &&
                    arg.charAt(offset0+1) != '+' &&
                    arg.charAt(offset0+1) != '-'
                    )
                return parentheses(arg.substring(0, offset1+1) +
                        "*" +
                        arg.substring(offset1+1));
        } catch (Exception e) {} // EOL
        return parentheses(arg.substring(0, offset0) +
                math(arg.substring(offset0+1, offset1)) +
                arg.substring(offset1+1));
    }

    static int deepest_parent(
            final String string,
            final int offset1,
            final int offset2)
            throws Exception
    {
        if (string.charAt(offset1) != '(')
            return deepest_parent(string, offset1+1, offset1+1);
        else {
            if (string.charAt(offset2) == '(')
                return deepest_parent(string, offset2, offset2+1);
            if (string.charAt(offset2) == ')')
                return offset1;
            return deepest_parent(string, offset1, offset2+1);
        }
    }

    static int last_integer(
            final int ret,
            final String string,
            final int increment,
            final boolean first_char)
    {
        try {
            if (string.charAt(ret) == '.' || string.charAt(ret) == 'E')
                return last_integer(ret+increment, string, increment, false);
            if (string.charAt(ret) == '-' && first_char && increment > 0)
                return last_integer(ret+increment, string, increment, true);
            Integer.parseInt(""+string.charAt(ret));
            if (ret == 1) return 0;
            return last_integer(ret+increment, string, increment, false);
        } catch (Exception e) {
            return ret+-increment;
        }
    }

    static String math(
            final String arg)
            throws Exception
    {
        String result = math_do(math_do(math_do(math_do(math_do( arg,
                        '^',1), '*',1), '/',1), '+',1), '-',1);
        return extra_operators(result);
    }

    static String extra_operators(
            final String string)
            throws Exception
    {
        try {
            final boolean is_same = string.charAt(0) == string.charAt(1);
            final boolean is_operator =
                    string.charAt(0) == '-' || string.charAt(0) == '+';
            if (is_same && is_operator) {
                return extra_operators(string.substring(2));
            }
        } catch (Exception e) {
        }
        return string;
    }

    static String math_do(
            final String arg,
            final char operator,
            final int offset)
            throws Exception
    {
        if (arg.indexOf(operator, offset) < 0) return arg;
        else {
            final int middle = arg.indexOf(operator, offset);
            if (operator == '-' && arg.charAt(middle-1) == 'E')
                return math_do(arg, operator, middle+1);
            final int left = last_integer(middle-1, arg, -1, true);
            final int right = last_integer(middle+1, arg, +1, true);
            final String a_sz = extra_operators(arg.substring(left, middle));
            final String b_sz = extra_operators(arg.substring(middle+1, right+1));
            if (a_sz.length() == 0 || b_sz.length() == 0) return arg;
            final float a = Float.parseFloat(a_sz);
            final float b = Float.parseFloat(b_sz);
            if (operator == '^') return math_do(arg.substring(0, left) +
                    Math.pow(a, b) +
                    arg.substring(right+1, arg.length()), operator, offset);
            if (operator == '*') return math_do(arg.substring(0, left) +
                    (a*b) +
                    arg.substring(right+1, arg.length()), operator, offset);
            if (operator == '/') return math_do(arg.substring(0, left) +
                    (a/b) +
                    arg.substring(right+1, arg.length()), operator, offset);
            if (operator == '+') return math_do(arg.substring(0, left) +
                    (a+b) +
                    arg.substring(right+1, arg.length()), operator, offset);
            if (operator == '-') return math_do(arg.substring(0, left) +
                    (a-b) +
                    arg.substring(right+1, arg.length()), operator, offset);
            System.exit(1); // fatal: parameter not acceptable
            return "";
        }
    }

}
Member Avatar
quuba
Posting Pro
573 posts since Nov 2008
Reputation Points: 81 [?]
Q&As Helped to Solve: 107 [?]
Skill Endorsements: 0 [?]
 
0
 

Do not forget the upcoming lunar eclipse.
http://en.wikipedia.org/wiki/December_2010_lunar_eclipse

Member Avatar
quuba
Posting Pro
573 posts since Nov 2008
Reputation Points: 81 [?]
Q&As Helped to Solve: 107 [?]
Skill Endorsements: 0 [?]
 
0
 

run:
0.5/2
RESULT: 0.25
.5/2
RESULT: 0.25
1E5/2
RESULT: 50000.0
E5/2
java.lang.NumberFormatException: For input string: "E5"

Member Avatar
seanbp
Junior Poster
129 posts since Jul 2010
Reputation Points: 4 [?]
Q&As Helped to Solve: 15 [?]
Skill Endorsements: 0 [?]
 
0
 

This code is much different than when I started this project. Note: Input with no operators is not processed. In such cases consider using (x)*1.

package jcalculator;

import java.util.Scanner;

public class Main {

    static final Scanner scanner = new Scanner(System.in);

    public static void main(
            String[] args) {
        do {
            try {
                final String line = scanner.nextLine();
                if (line.length() == 0) {
                    return;
                }
                System.out.println(line + " = " + parentheses(line));
            } catch (Exception e) {
                System.out.println(e);
            }
        } while (true);
    }
    static String parentheses(final String arg) throws Exception {
        if (arg.indexOf('(') < 0) return math(arg);
        final int offset0 = deepest_parent(arg, 0, 0);
        final int offset1 = arg.indexOf(')', offset0);
        if (offset0 - 1 >= 0 &&
                !parentheses_multipliers(arg, offset0-1, +1, '(').equals(arg))
            return parentheses(parentheses_multipliers(arg, offset0-1, +1, '('));
        if (offset1 + 1 < arg.length() &&
                !parentheses_multipliers(arg, offset1+1, 0, ')').equals(arg))
            return parentheses(parentheses_multipliers(arg, offset1+1, 0, ')'));
        return parentheses(arg.substring(0, offset0)
                + math(arg.substring(offset0 + 1, offset1))
                + arg.substring(offset1 + 1));
    }

    static String parentheses_multipliers(
            final String arg,
            final int location,
            final int offset,
            final char character)
            throws Exception
    {
        if (arg.charAt(location) != '*' &&
            arg.charAt(location) != '^' &&
            arg.charAt(location) != '/' &&
            arg.charAt(location) != '+' &&
            arg.charAt(location) != '-' &&
            arg.charAt(location) != character)
                return arg.substring(0, location+offset) + "*" + arg.substring(location+offset);
            return arg;
    }

    static int deepest_parent(
            final String string,
            final int offset1,
            final int offset2)
            throws Exception
    {
        if (string.charAt(offset1) != '(') {
            return deepest_parent(string, offset1 + 1, offset1 + 1);
        } else {
            if (string.charAt(offset2) == '(') {
                return deepest_parent(string, offset2, offset2 + 1);
            }
            if (string.charAt(offset2) == ')') {
                return offset1;
            }
            return deepest_parent(string, offset1, offset2 + 1);
        }
    }

    static int last_integer(
            final int ret,
            final String string,
            final int increment, 
            final boolean first_char)
    {
        if (ret == string.length()) return string.length() - 1;
        if (string.charAt(ret) == '.' || string.charAt(ret) == 'E')
            return last_integer(ret + increment, string, increment, false);
        if (string.charAt(ret) == '-' && first_char && increment > 0)
            return last_integer(ret + increment, string, increment, true);
        if (string.charAt(ret) == '-' &&
                !first_char && increment < 0 &&
                ret > 1 &&
                string.charAt(ret-1) == 'E')
            return last_integer(ret + increment * 2, string, increment, false);
        if (!is_int(string.charAt(ret))) return ret + -increment;
        if (ret < 2) return 0;
        return last_integer(ret + increment, string, increment, false);
    }

    final static boolean is_int(final char string) {
        if (string == '0'
                || string == '1'
                || string == '2'
                || string == '3'
                || string == '4'
                || string == '5'
                || string == '6'
                || string == '7'
                || string == '8'
                || string == '9') {
            return true;
        }
        return false;

    }

    static String math(final String arg) throws Exception {
        final String result = math_do( math_do( math_do( math_do( math_do( arg,
                               '^', 1), '*', 1), '/', 1), '+', 1), '-', 1);
        return extra_signs(result);
    }

    static String extra_signs(final String string) throws Exception {
        if (string.length() < 2) return string;
        final boolean is_same = string.charAt(0) == string.charAt(1);
        final boolean is_operator = string.charAt(0) == '-';
        if (is_same && is_operator) return extra_signs(string.substring(2));
        return string;
    }

    static String math_do(
            final String arg,
            final char operator,
            final int offset)
            throws Exception {
        if (arg.indexOf(operator, offset) < 0) {
            return arg;
        } else {
            if (!extra_signs(arg).equals(arg))
                return math_do(extra_signs(arg), operator, offset);
            final int middle = arg.indexOf(operator, offset);
            if (operator == '-' && arg.charAt(middle - 1) == 'E')
                return math_do(arg, operator, middle + 1);
            final int left = last_integer(middle - 1, arg, -1, true);
            final int right = last_integer(middle + 1, arg, +1, true);
            final String a_sz = extra_signs(arg.substring(left, middle));
            final String b_sz = extra_signs(arg.substring(middle + 1, right + 1));
            if (a_sz.length() == 0 || b_sz.length() == 0) return arg;
            final float a = Float.parseFloat(a_sz);
            final float b = Float.parseFloat(b_sz);
            if (operator == '^')
                return math_do(arg.substring(0, left) + Math.pow(a, b)
                        + arg.substring(right + 1, arg.length()), operator, offset);
            if (operator == '*')
                return math_do(arg.substring(0, left) + (a * b)
                        + arg.substring(right + 1, arg.length()), operator, offset);
            if (operator == '/')
                return math_do(arg.substring(0, left) + (a / b)
                        + arg.substring(right + 1, arg.length()), operator, offset);
            if (operator == '+')
                return math_do(arg.substring(0, left) + (a + b)
                        + arg.substring(right + 1, arg.length()), operator, offset);
            if (operator == '-')
                return math_do(arg.substring(0, left) + (a - b)
                        + arg.substring(right + 1, arg.length()), operator, offset);
            System.exit(1); // fatal: parameter not acceptable
            return "";
        }
    }
}
Member Avatar
quuba
Posting Pro
573 posts since Nov 2008
Reputation Points: 81 [?]
Q&As Helped to Solve: 107 [?]
Skill Endorsements: 0 [?]
 
0
 

Note: Input with no operators is not processed. In such cases consider using (x)*1.

Line 17

System.out.println(line + " = " + Float.parseFloat(parentheses(line)));

----------------1----------------1 = 2.0 nice
++++++++++++++++1++++++++++++++++1 = 2.0 at me nice too

Member Avatar
seanbp
Junior Poster
129 posts since Jul 2010
Reputation Points: 4 [?]
Q&As Helped to Solve: 15 [?]
Skill Endorsements: 0 [?]
 
0
 

Line 17

System.out.println(line + " = " + Float.parseFloat(parentheses(line)));

I decided to omit the translation to float for better precision.

Question Answered as of 3 Years Ago by quuba
You
This question has already been solved: Start a new discussion instead
Post:
Start New Discussion
Tags Related to this Article