This site requires JavaScript, please enable it in your browser!
Greenfoot back
Gevater_Tod4711
Gevater_Tod4711 wrote ...

2012/10/17

Way to get mathematical formulas by input?

Gevater_Tod4711 Gevater_Tod4711

2012/10/17

#
Hi all, I want to create a program to show the graph of an mathematikal formula but I don't know how I can get an input string into a formula java can use to calculate. Has anyone an idea how I could do this?
danpost danpost

2012/10/17

#
Believe me, that is no easy task! It takes a method call to the executing method. For example, let us say we have a method called 'process()'. Then
private String process(String str)
{
    // some code
    if (someCondition) process(str2)
    // some code
}
The above code is no neccessarily anything that you would be using in your code. I gave it only to show what I meant by a method calling itself ('a method call to the executing method'). To complicate matters even more, every situation (that you might allow) must be individually accounted for and dealt with accordingly. The more control you have on the syntax of the equation, the better off you will be on coding to transfer from String to Java values and operations. Are you trying to do something like this?
actinium actinium

2012/10/17

#
I like this blogg. This guy knows his stuff.
Gevater_Tod4711 Gevater_Tod4711

2012/10/17

#
@danpost well a method call to the executing method wouldn't be a problem. I still know this stuff from quicksort or other sings from shool. But I don't get how this will help me. I'd like to programm something like the scanario in your link but I want to have an input so that I can change the formula I'm using. Creating this with a formular which is in the code wouldn't be a problem but I don't know how to get the string into a mathematic formular. The transfer from string into values would also be no problem (not realy) but how could I transfer the string into mathematik operations?
danpost danpost

2012/10/17

#
Check out the scenario again. This time click on the formula at the lower right of the screen (or just press 'ENTER' or 'ESC') after clicking on'Run' or pressing 'Ctrl-R'. Like I said everything will have to be accounted for '+', '-', '*', '/'... EVERYTHING!! You will probably end up with a method call with two parameters for each one (what is on the left of the operator and what is on the right).
Gevater_Tod4711 Gevater_Tod4711

2012/10/17

#
Oh ok I think I understod now. It will be very tricky I know but I'll try it. Thank you for the help.
Gevater_Tod4711 Gevater_Tod4711

2012/10/20

#
I need help again. I now got a method that calculates values from a string but it ignores some mathematic rules like * and / befor + and -. It just gives on the value and calculates from the beginning to the end of the string. Do I have to cut the whole string into parts to calculate them on there own or is there an easyer way?
danpost danpost

2012/10/20

#
If you can think of an easier way, go for it (I could not). Otherwise, cutting the whole string into parts (which is basically what I did in my 'Equation Grapher' scenario) is what needs done. This is where it gets tricky! That and dealing with parenthesis.
Gevater_Tod4711 Gevater_Tod4711

2012/10/20

#
Well, I also got no better idea so I already did it with cutting the string into parts. This also lead to a result.
Duta Duta

2012/12/16

#
I know this post is old, but I only just came across it. I've just thrown together a very, very simple parser, if anyone's interested (you can extend it if you want - I've got an essay to write currently, so I don't have the time). Currently it only supports addition and multiplication, but it shouldn't be too hard to extend it. Bear in mind this parser naively assumes you've passed it a well-formed string (i.e. consisting solely of '+'s, '*'s, digits and spaces). This can be extended to work with doubles instead of ints simply by changing all of the method return types to double and changing Integer.parseInt(equation) to Double.parseDouble(equation):
public class Parser {
    /**
     * Parses simple equations such as:
     * "2*3 + 3*4"
     * 
     *            ~Duta
     */
    public static int parseEquation(String equation) {
    	// Remove any spaces.
    	for(int i = 0; i < equation.length(); i++) {
    		if(equation.charAt(i) == ' ') {
    			String leftSide = "";
    			String rightSide = "";
    			for(int i2 = 0; i2 < i; i2++) {
    				leftSide += equation.charAt(i2);
    			}
    			for(int i2 = i + 1; i2 < equation.length(); i2++) {
    				rightSide += equation.charAt(i2);
    			}
    			equation = leftSide + rightSide;
    			i--;
    		}
    	}
    
    	// Parse the equation.
    	if(equation.length() == 0) {
    		return 0;
    	}
    	return parseAdditive(equation);
    }
    
    private static int parseAdditive(String equation) {
    	// Try to pattern match it to:
    	// multiplicative + additive
    	// If that fails, match it to:
    	// multiplicative
    	int plusIndex = equation.indexOf('+');
    	if(plusIndex != -1) {
    		String leftSide = "";
    		String rightSide = "";
    		for(int i2 = 0; i2 < plusIndex; i2++) {
    			leftSide += equation.charAt(i2);
    		}
    		for(int i2 = plusIndex + 1; i2 < equation.length(); i2++) {
    			rightSide += equation.charAt(i2);
    		}
    		return parseMultiplicative(leftSide) + parseAdditive(rightSide);
    	} else {
    		return parseMultiplicative(equation);
    	}
    }
    
    private static int parseMultiplicative(String equation) {
    	// Try to pattern match it to:
    	// integer * multiplicative
    	// If that fails, match it to:
    	// integer
    	int timesIndex = equation.indexOf('*');
    	if(timesIndex != -1) {
    		String leftSide = "";
    		String rightSide = "";
    		for(int i2 = 0; i2 < timesIndex; i2++) {
    			leftSide += equation.charAt(i2);
    		}
    		for(int i2 = timesIndex + 1; i2 < equation.length(); i2++) {
    			rightSide += equation.charAt(i2);
    		}
    		return parseInteger(leftSide) * parseMultiplicative(rightSide);
    	} else {
    		return parseInteger(equation);
    	}
    }
    
    private static int parseInteger(String equation) {
    	return Integer.parseInt(equation);
    }
}
Duta Duta

2012/12/17

#
I made a start on the essay, then I came back and added support for parentheses:
public class Parser {
    /**
     * Parses simple equations such as:
     * "(2 + (3 + 3)*4)/-0.5"
     * (to produce -52)
     * 
     *            ~Duta
     */
    public static double parseEquation(String equation) {
        // Remove any spaces.
        for(int i = 0; i < equation.length(); i++) {
            if(equation.charAt(i) == ' ') {
                String leftSide = "";
                String rightSide = "";
                for(int i2 = 0; i2 < i; i2++) {
                    leftSide += equation.charAt(i2);
                }
                for(int i2 = i + 1; i2 < equation.length(); i2++) {
                    rightSide += equation.charAt(i2);
                }
                equation = leftSide + rightSide;
                i--;
            }
        }
    
        // Parse the equation.
        if(equation.length() == 0) {
            return 0;
        }
        return parseAdd(equation);
    }
    
    private static double parseAdd(String equation) {
        // Try to pattern match it to:
        // multiplicative + additive
        // If that fails, match it to:
        // multiplicative
        int plusIndex = getIndex(equation, '+');
        if(plusIndex != -1) {
            String leftSide = equation.substring(0, plusIndex);
            String rightSide = equation.substring(plusIndex + 1, equation.length());
            return parseTimesDivide(leftSide) + parseAdd(rightSide);
        } else {
            return parseTimesDivide(equation);
        }
    }
    
    private static double parseTimesDivide(String equation) {
        // Try to pattern match it to:
        // parentheses * timesdivide
        // If that fails, match it to:
        // parentheses / timesdivide
        // If that fails, match it to:
        // parentheses
        int timesIndex = getIndex(equation, '*');
        if(timesIndex != -1) {
            String leftSide = equation.substring(0, timesIndex);
            String rightSide = equation.substring(timesIndex + 1, equation.length());
            return parseParentheses(leftSide) * parseTimesDivide(rightSide);
        } else {
            int divIndex = getIndex(equation, '/');
            if(divIndex != -1) {
                String leftSide = equation.substring(0, divIndex);
                String rightSide = equation.substring(divIndex + 1, equation.length());
                return parseParentheses(leftSide) / parseTimesDivide(rightSide);
            } else {
                return parseParentheses(equation);
            }
        }
    }
    
    private static double parseParentheses(String equation) {
        // Try to pattern match it to:
        // (additive)
        // If that fails, match it to:
        // number
        if(equation.length() > 2 && equation.charAt(0) == '(' && equation.charAt(equation.length() - 1) == ')') {
            String middle = equation.substring(1, equation.length() - 1);
            return parseAdd(middle);
        } else {
            return parseNum(equation);
        }
    }
    
    private static double parseNum(String equation) {
        return Double.parseDouble(equation);
    }
    
    private static int getIndex(String equation, char chr) {
        int chIndex;
        int fromPoint = 0;
        while(true) {
            chIndex = equation.indexOf(chr, fromPoint);
            if(chIndex == -1) break;
            int leftOpenCount = 0;
            int leftCloseCount = 0;
            int rightOpenCount = 0;
            int rightCloseCount = 0;
            for(int i2 = 0; i2 < chIndex; i2++) {
                char ch = equation.charAt(i2);
                if(ch == '(') leftOpenCount++;
                else if(ch == ')') leftCloseCount++;
            }
            for(int i2 = chIndex + 1; i2 < equation.length(); i2++) {
                char ch = equation.charAt(i2);
                if(ch == '(') rightOpenCount++;
                else if(ch == ')') rightCloseCount++;
            }
            if(leftOpenCount == leftCloseCount
            && rightOpenCount == rightCloseCount) {
                break;
            } else {
                fromPoint = chIndex + 1;
            }
        }
        return chIndex;
    }
}
EDIT: And division. I've really got to go to sleep now though.
Duta Duta

2012/12/17

#
Couldn't sleep (going to go try again now). Sorry for all of these posts... hopefully someone finds this useful. Here's the updated version (now has support for addition, subtraction, multiplication, division, exponentiation and parentheses):
public class Parser {
    /**
     * Parses equations such as:
     * "(2 + (3 + 3)*4)/(-0.25^0.5)"
     * (to produce -52)
     * 
     *            ~Duta
     */
    public static double parseEquation(String equation) {
        // Remove any spaces.
        for(int i = 0; i < equation.length(); i++) {
            if(equation.charAt(i) == ' ') {
                String leftSide = "";
                String rightSide = "";
                for(int i2 = 0; i2 < i; i2++) {
                    leftSide += equation.charAt(i2);
                }
                for(int i2 = i + 1; i2 < equation.length(); i2++) {
                    rightSide += equation.charAt(i2);
                }
                equation = leftSide + rightSide;
                i--;
            }
        }
    
        // Parse the equation.
        if(equation.length() == 0) {
            return 0;
        }
        return parseAddSubtract(equation);
    }
    
    private static double parseAddSubtract(String equation) {
        // Try to pattern match it to:
        // multiplicative + addsubtract
        // If that fails, match it to:
        // multiplicative
        int plusIndex = getIndex(equation, '+');
        if(plusIndex != -1) {
            String leftSide = equation.substring(0, plusIndex);
            String rightSide = equation.substring(plusIndex + 1, equation.length());
            return parseTimesDivide(leftSide) + parseAddSubtract(rightSide);
        } else {
            int minusIndex = getIndex(equation, '-');
            if(minusIndex != -1) {
                String leftSide = equation.substring(0, minusIndex);
                String rightSide = equation.substring(minusIndex + 1, equation.length());
                leftSide = leftSide.equals("") ? "0" : leftSide;
                return parseTimesDivide(leftSide) - parseAddSubtract(rightSide);
            } else {
                return parseTimesDivide(equation);
            }
        }
    }
    
    private static double parseTimesDivide(String equation) {
        // Try to pattern match it to:
        // power * timesdivide
        // If that fails, match it to:
        // power / timesdivide
        // If that fails, match it to:
        // power
        int timesIndex = getIndex(equation, '*');
        if(timesIndex != -1) {
            String leftSide = equation.substring(0, timesIndex);
            String rightSide = equation.substring(timesIndex + 1, equation.length());
            return parsePower(leftSide) * parseTimesDivide(rightSide);
        } else {
            int divIndex = getIndex(equation, '/');
            if(divIndex != -1) {
                String leftSide = equation.substring(0, divIndex);
                String rightSide = equation.substring(divIndex + 1, equation.length());
                return parsePower(leftSide) / parseTimesDivide(rightSide);
            } else {
                return parsePower(equation);
            }
        }
    }
    
    private static double parsePower(String equation) {
        // Try to pattern match it to:
        // parentheses ^ parentheses
        // If that fails, match it to:
        // parentheses
        int powerIndex = getIndex(equation, '^');
        if(powerIndex != -1) {
            String leftSide = equation.substring(0, powerIndex);
            String rightSide = equation.substring(powerIndex + 1, equation.length());
            return Math.pow(parseParentheses(leftSide), parseParentheses(rightSide));
        } else {
            return parseParentheses(equation);
        }
    }
    
    private static double parseParentheses(String equation) {
        // Try to pattern match it to:
        // (additive)
        // If that fails, match it to:
        // number
        if(equation.length() > 2 && equation.charAt(0) == '(' && equation.charAt(equation.length() - 1) == ')') {
            String middle = equation.substring(1, equation.length() - 1);
            return parseAddSubtract(middle);
        } else {
            return parseNum(equation);
        }
    }
    
    private static double parseNum(String equation) {
        return Double.parseDouble(equation);
    }
    
    private static int getIndex(String equation, char chr) {
        int chIndex;
        int fromPoint = 0;
        while(true) {
            chIndex = equation.indexOf(chr, fromPoint);
            if(chIndex == -1) break;
            int leftOpenCount = 0;
            int leftCloseCount = 0;
            int rightOpenCount = 0;
            int rightCloseCount = 0;
            for(int i2 = 0; i2 < chIndex; i2++) {
                char ch = equation.charAt(i2);
                if(ch == '(') leftOpenCount++;
                else if(ch == ')') leftCloseCount++;
            }
            for(int i2 = chIndex + 1; i2 < equation.length(); i2++) {
                char ch = equation.charAt(i2);
                if(ch == '(') rightOpenCount++;
                else if(ch == ')') rightCloseCount++;
            }
            if(leftOpenCount == leftCloseCount
            && rightOpenCount == rightCloseCount) {
                break;
            } else {
                fromPoint = chIndex + 1;
            }
        }
        return chIndex;
    }
}
MatheMagician MatheMagician

2012/12/17

#
Cool! I spent quite a while getting it to work the hard way, with just string modifiers like getCharAt() and such:(
Duta Duta

2012/12/17

#
Sorry to post again. I'm only posting an updated version of the parser because I realized that subtraction is bugged in the previous version. I've fixed it (and added trig functions):
public class Parser {
    /**
     * Parses equations such as:
     * "(sin(90) - -1 + (3 + 3)*4)/(-0.25^0.5)"
     * (to produce -52)
     * 
     *            ~Duta
     */
    public static double parseEquation(String equation) {
        // Remove any spaces.
        for(int i = 0; i < equation.length(); i++) {
            if(equation.charAt(i) == ' ') {
                String leftSide = equation.substring(0, i);
                String rightSide = equation.substring(i + 1, equation.length());
                equation = leftSide + rightSide;
                i--;
            }
        }
        
        // Convert any "--"s to "+"s
        for(int i = 1; i < equation.length(); i++) {
            if(equation.charAt(i-1) == '-'
            && equation.charAt(i) == '-') {
                String leftSide = equation.substring(0, i-1);
                String rightSide = equation.substring(i + 1, equation.length());
                equation = leftSide + '+' + rightSide;
                i--;
            }
        }
    
        // Parse the equation.
        if(equation.length() == 0) {
            return 0;
        }
        try {
            return parseAddSubtract(equation);
        } catch(Exception e) {
            System.out.println("Something went wrong.");
            return 0;
        }
    }
    
    private static double parseAddSubtract(String equation) throws Exception {
        // Try to pattern match it to:
        // timesdivide + addsubtract
        // If that fails, match it to:
        // timesdivide - addsubtract
        // If that fails, match it to:
        // timesdivide
        int plusIndex = getIndex(equation, '+');
        if(plusIndex != -1) {
            String leftSide = equation.substring(0, plusIndex);
            String rightSide = equation.substring(plusIndex + 1, equation.length());
            return parseTimesDivide(leftSide) + parseAddSubtract(rightSide);
        } else {
            int minusIndex = getIndex(equation, '-');
            if(minusIndex != -1) {
                String leftSide = equation.substring(0, minusIndex);
                String rightSide = equation.substring(minusIndex + 1, equation.length());
                leftSide = leftSide.equals("") ? "0" : leftSide;
                return parseTimesDivide(leftSide) - parseAddSubtract(rightSide);
            } else {
                return parseTimesDivide(equation);
            }
        }
    }
    
    private static double parseTimesDivide(String equation) throws Exception {
        // Try to pattern match it to:
        // power * timesdivide
        // If that fails, match it to:
        // power / timesdivide
        // If that fails, match it to:
        // power
        int timesIndex = getIndex(equation, '*');
        if(timesIndex != -1) {
            String leftSide = equation.substring(0, timesIndex);
            String rightSide = equation.substring(timesIndex + 1, equation.length());
            return parsePower(leftSide) * parseTimesDivide(rightSide);
        } else {
            int divIndex = getIndex(equation, '/');
            if(divIndex != -1) {
                String leftSide = equation.substring(0, divIndex);
                String rightSide = equation.substring(divIndex + 1, equation.length());
                return parsePower(leftSide) / parseTimesDivide(rightSide);
            } else {
                return parsePower(equation);
            }
        }
    }
    
    private static double parsePower(String equation) throws Exception {
        // Try to pattern match it to:
        // parentheses ^ parentheses
        // If that fails, match it to:
        // parentheses
        int powerIndex = getIndex(equation, '^');
        if(powerIndex != -1) {
            String leftSide = equation.substring(0, powerIndex);
            String rightSide = equation.substring(powerIndex + 1, equation.length());
            return Math.pow(parseParentheses(leftSide), parseParentheses(rightSide));
        } else {
            return parseParentheses(equation);
        }
    }
    
    private static double parseParentheses(String equation) throws Exception {
        // Try to pattern match it to:
        // (additive)
        // If that fails, match it to:
        // func
        if(equation.length() > 2 && equation.charAt(0) == '(' && equation.charAt(equation.length() - 1) == ')') {
            String middle = equation.substring(1, equation.length() - 1);
            return parseAddSubtract(middle);
        } else {
            return parseFunc(equation);
        }
    }
    
    private static double parseFunc(String equation) throws Exception {
        // Try to pattern match it to:
        // sin(additive)
        // If that fails, match it to:
        // cos(additive)
        // If that fails, match it to:
        // tan(additive)
        // If that fails, match it to:
        // num
        if(equation.length() > 5 && equation.substring(0, 4).equalsIgnoreCase("sin(") && equation.charAt(equation.length() - 1) == ')') {
            String middle = equation.substring(4, equation.length() - 1);
            return Math.sin(Math.toRadians(parseAddSubtract(middle)));
        } else if(equation.length() > 5 && equation.substring(0, 4).equalsIgnoreCase("cos(") && equation.charAt(equation.length() - 1) == ')') {
            String middle = equation.substring(4, equation.length() - 1);
            return Math.cos(Math.toRadians(parseAddSubtract(middle)));
        } else if(equation.length() > 5 && equation.substring(0, 4).equalsIgnoreCase("tan(") && equation.charAt(equation.length() - 1) == ')') {
            String middle = equation.substring(4, equation.length() - 1);
            return Math.tan(Math.toRadians(parseAddSubtract(middle)));
        } else {
            return parseNum(equation);
        }
    }
    
    private static double parseNum(String equation) throws Exception {
        return Double.parseDouble(equation);
    }
    
    private static int getIndex(String equation, char chr) {
        int chIndex;
        int fromPoint = 0;
        while(true) {
            chIndex = equation.indexOf(chr, fromPoint);
            if(chIndex == -1) break;
            int leftOpenCount = 0;
            int leftCloseCount = 0;
            int rightOpenCount = 0;
            int rightCloseCount = 0;
            for(int i2 = 0; i2 < chIndex; i2++) {
                char ch = equation.charAt(i2);
                if(ch == '(') leftOpenCount++;
                else if(ch == ')') leftCloseCount++;
            }
            for(int i2 = chIndex + 1; i2 < equation.length(); i2++) {
                char ch = equation.charAt(i2);
                if(ch == '(') rightOpenCount++;
                else if(ch == ')') rightCloseCount++;
            }
            if(leftOpenCount == leftCloseCount
            && rightOpenCount == rightCloseCount) {
                break;
            } else {
                fromPoint = chIndex + 1;
            }
        }
        return chIndex;
    }
}
Duta Duta

2012/12/18

#
If anyone's actually interested in my Parser class (unlikely, I know), go here. Don't use any of the versions I posted in this thread that support subtraction, because they're bugged. They treat "7-5-9.5" as "7-(5-9.5)" instead of the intended "(7-5)-9.5". EDIT: Fixed link. EDIT2: Turned out division was bugged as well (it was the same bug as for subtraction). If you follow my link, you'll find I've extended it into a stable (i.e. non-buggy) class with many features. If you have any suggestions for it, please tell me them :)
You need to login to post a reply.