Stack problem java. Postfix Evaluation - java

Hey Guys I'm having a problem when I run my program. In the PostfixEvaluate() Method is where it takes in a string and solves the postfix problem and returns it. Well when I go to run it, I'm getting a bunch of random numbers(some repeated), I'm going crazy because I don't know what else to try and I've spent more time on this than it should normally take.
Heres the PostfixEvaluate Method:
public int PostfixEvaluate(String e){
//String Operator = "";
int number1;
int number2;
int result=0;
char c;
//number1 = 0;
//number2 = 0;
for(int j = 0; j < e.length(); j++){
c = e.charAt(j);
if (c != '+'&& c!= '*' && c!= '-' && c!= '/') {
//if (c == Integer.parseInt(e)) {
s.push(c);
}
else {
number1 = s.pop();
number2 = s.pop();
switch(c) {
case '+':
result = number1 + number2;
break;
case '-':
result = number1 - number2;
break;
case '*':
result = number1 * number2;
break;
case '/':
result = number1 / number2;
break;
} s.push(result);
}
System.out.println(result);
}
return s.pop();
}
public static void main(String[] args) {
Stacked st = new Stacked(100);
String y = new String("(z * j)/(b * 8) ^2");
String x = new String("2 3 + 9 *");
TestingClass clas = new TestingClass(st);
clas.test(y);
clas.PostfixEvaluate(x);
}
}
This is the Stack Class:
public class Stacked {
int top;
char stack[];
int maxLen;
public Stacked(int max) {
top = -1;
maxLen = max;
stack = new char[maxLen];
}
public void push(int result) {
top++;
stack[top] = (char)result;
}
public int pop() {
int x;
x = stack[top];
//top = top - 1;
top--;
return x;
}
public boolean isStackEmpty() {
if(top == -1) {
System.out.println("Stack is empty " + "Equation Good");
return true;
}
else
System.out.println("Equation is No good");
return false;
}
public void reset() {
top = -1;
}
public void showStack() {
System.out.println(" ");
System.out.println("Stack Contents...");
for(int j = top; j > -1; j--){
System.out.println(stack[j]);
}
System.out.println(" ");
}
public void showStack0toTop() {
System.out.println(" ");
System.out.println("Stack Contents...");
for(int j=0; j>=top; j++){
System.out.println(stack[j]);
}
System.out.println(" ");
}
}

It looks to me like you aren't handling spaces at all.
This means that when you put in a space, it is implicitly converting the character space to the ascii value of it (32) when it pops it off the stack during an operation. Also, it looks like you are assuming that all numbers/results will be single digit, and casting from char to int, which is not what you want to do, since that will convert the char to the ascii value of the char, ' ' -> 32, '3' -> 51, etc.
If I were you, I would do this for your loop in PostfixEvaluate:
while(!e.equals("")){
string c;
int space = e.indexOf(' ');
if(space!=-1){
c = e.substring(0,space);
e = e.substring(space+2);
} else{
c = e;
e = "";
}
if (!c.equals("+")&& !c.equal("*") && !c.equals("-") && !c.equals("/")) {
//...
}
and change your stack to hold strings or ints.

The problem is that you are pushing char onto a stack as an int, so you are unintentionally working with the ascii representations of numbers, which is not the actual value of the number.
Instead of this complicated character walking, tokenize the input string using String.split(). Example:
String[] tokens = e.split(" ");
for(String token:tokens){
if (!"+".equals(token) && !"*".equals(token) && !"-".equals(token) && !"/".equals(token)) {
s.push(Integer.parseInt(token));
} else {
....
}
}

You need to split the string into tokens first:
/* Splits the expression up into several Strings,
* all of which are either a number or and operator,
* none of which have spaces in them. */
String [] expressionAsTokens = e.split(" ");
Then you need to make sure you compare Strings, not chars:
//compare strings instead of chars
String token = expressionAsTokens[j];
if (!"+".equals(token) && !"*".equals(token) && !"-".equals(token) && !"/".equals(token)) {
s.push(Integer.parseInt(token));
} else {
//same code as you had before
}
Also, is there any reason you are storing everything as a char array in your Stacked class? Your pop() method returns and integer, yet everything is stored as a char.
For this application, everything should be stored as an integer:
public class Stacked {
int stack[]; // array is of type integer
int top;
int maxLen;
// constructor
public void push() {/*...*/}
public int pop() {/*...*/} //pop returns an int as before
//...
}
One final note: Be careful what order you add and subtract the numbers in. I don't remember if postfix operands are evaluated left first or right first, but make sure you get them in the right order. As you have it now, 2 3 - 4 * would evaluate as 4 * (3 - 2) and I think it should be (2 - 3) * 4. This won't matter with adding and multiplying, but it will with subtracting and dividing.

Related

String Math Algorithm Gone Wrong JavaFX

As I was building my first JavaFX project, I noticed that the calculator engine that I had built was a little off. With that being said, I went over my code for about an hour now, trying to figure out what is wrong and I couldn't find anything that connects to this strange bug in my program.
The calculator engine:
public static String BasicEval(String str, String function) {
int indexOfOperation = str.indexOf(function);
int downBoundary = indexOfOperation - 1;
int upBoundary = indexOfOperation + 1;
int closestUp = str.length(), closestDown = 0;
for (int index = 0; index < str.length(); index++) { // Searching for the closest white space (between vals.) to determine what are the two vals.
if (Math.abs(indexOfOperation - index) == 1) {
continue;
} else if ((str.charAt(index) == ' ') && ((indexOfOperation - index) > closestDown)) {
closestDown = index; //Finds the closest blank space in order to differentiate between elements.
} else if ((str.charAt(index) == ' ') && (Math.abs(indexOfOperation + index) < closestUp)) {
closestUp = index; //Finds the closest black space in order to differentiate between elements.
}
}
while (str.substring(upBoundary,closestUp).contains("X") || (str.substring(upBoundary,closestUp).contains("-") || (str.substring(upBoundary,closestUp).contains("+") || (str.substring(upBoundary,closestUp).contains("/") || (str.substring(upBoundary,closestUp).contains("^")))))) {
closestUp--;
}
double firstValue = Double.valueOf(str.substring((closestDown + 1), downBoundary));
double secondValue = Double.valueOf(str.substring(upBoundary + 1, (closestUp-1)));
double OperationResult;
switch (function) {
case "^" : OperationResult = Math.pow(firstValue,secondValue); break;
case "X" : OperationResult = (firstValue * secondValue); break;
case "/" : OperationResult = (firstValue / secondValue); break;
case "+" : OperationResult = (firstValue + secondValue); break;
case "-" : OperationResult = firstValue - secondValue; break;
default: OperationResult = -999.12349876; //ERROR
}
str = strSort(str,firstValue,secondValue,OperationResult);
return str;
}
A little bit about the engine: the engine itself supposes to evaluate math expressions inside strings, so for example an input would be: " 3 + 4 " and the answer would be: 7.0 as a double. The way I hoped to achive this was by deviding the str into 4 smaller sections by the spaces between the terms and operation sign. The problem is: the math gets all wierd as you use bigger numbers. The number -999.123... stands for an error in my program.
The engine works just fine for simple calculations that use low numbers, but as you start to use bigger numbers things get messy. Sometimes it also produces errors like: "empty string", which I don't understand why ..
For more info about the project or the engine please comment.
-- Keep in mind that I'm looking for an answer that would apply to my algorithm, not to javaFX in general-- (though I'd love to learn new stuff)
Thanks !!
Examples of how things aren't as they should be:
enter image description here
enter image description here
I'll post more pictures in the comments.
strSort Method
public static String strSort(String str, double firstValue, double secondValue, double result) {
//Method that sorts between which vals are ints and which ones are doubles. --> returns them in their current form.
int firstValueIndex = 0;
int secondValueIndex = 0;
if (!intOrDoubleTest(firstValue) && firstValue == secondValue){ // Special category : indexOf doesn't work since the two vals. are the same --> giving off the same index.
firstValueIndex = str.indexOf(Double.toString(firstValue));
secondValueIndex = str.indexOf(Double.toString(secondValue),firstValueIndex+1);
} else if (intOrDoubleTest(firstValue) && firstValue == secondValue) { // Special category : indexOf doesn't work since the two vals. are the same --> giving off the same index.
firstValueIndex = str.indexOf(Integer.toString(intValue(firstValue)));
secondValueIndex = str.indexOf(Integer.toString(intValue(secondValue)),firstValueIndex+1);
} else if (intOrDoubleTest(firstValue) && intOrDoubleTest(secondValue)) { // First, sorts out the two vals.
firstValueIndex = str.indexOf(Integer.toString(intValue(firstValue)));
secondValueIndex = str.indexOf(Integer.toString(intValue(secondValue)));
} else if (!intOrDoubleTest(firstValue) && intOrDoubleTest(secondValue)) {
firstValueIndex = str.indexOf(Double.toString(firstValue));
secondValueIndex = str.indexOf(Integer.toString(intValue(secondValue)));
} else if (intOrDoubleTest(firstValue) && !intOrDoubleTest(secondValue)) {
firstValueIndex = str.indexOf(Integer.toString(intValue(firstValue)));
secondValueIndex = str.indexOf(Double.toString(secondValue));
} else if (!intOrDoubleTest(firstValue) && !intOrDoubleTest(secondValue)) {
firstValueIndex = str.indexOf(Double.toString(firstValue));
secondValueIndex = str.indexOf(Double.toString(secondValue));
}
String strToReplace = str.substring(firstValueIndex, secondValueIndex); // Computing the range that need to be replaced.
if (intOrDoubleTest(result)) {
int intResult = intValue(result);
str = str.replace(strToReplace,Integer.toString(intResult));
} else if (!intOrDoubleTest(result)) {
str = str.replace(strToReplace,Double.toString(result));
}
return str;
}
public static boolean intOrDoubleTest(double value) {
return (value % 1 == 0); // True = val is Int, False = val is Double.
}
Found the problem:
The problem was in the strToReplace.substring the strSort method. So naturally, I re-wrote the entire method in a much simpler, nicer way.
public static String strSort(String str, double firstValue, double secondValue, double result) {
//Method that sorts between which vals are ints and which ones are doubles. --> returns them in their current form.
int firstValueIndex;
int secondValueIndex;
if (intOrDoubleTest(firstValue)) {
firstValueIndex = str.indexOf(Integer.toString(intValue(firstValue)));
} else {
firstValueIndex = str.indexOf(Double.toString(firstValue));
}
if (intOrDoubleTest(secondValue)) {
secondValueIndex = str.indexOf(Integer.toString(intValue(secondValue)), firstValueIndex+1);
} else {
secondValueIndex = str.indexOf(Double.toString(secondValue), firstValueIndex+1);
}
int lengthOfSecondVal;
lengthOfSecondVal = (int)(Math.log10(secondValue)+1);
String strToReplace = str.substring(firstValueIndex, secondValueIndex+lengthOfSecondVal); // Computing the range that need to be replaced.
if (intOrDoubleTest(result)) {
int intResult = intValue(result);
str = str.replace(strToReplace,Integer.toString(intResult));
} else if (!intOrDoubleTest(result)) {
str = str.replace(strToReplace,Double.toString(result));
}
return str;
}
public static boolean intOrDoubleTest(double value) {
return (value % 1 == 0); // True = val is Int, False = val is Double.
}
Thank you to all of you that helped !!

how can I check if a string is a floating point number?

In my program I'm going to store user input in an array then going to check each character to see if it's a digit or dot or E or negative sign after that I'll store it in to an array called temps.
Now I have problem in my fleating method () that don't how should I make my condition for the pattern of floating number digit-digit-dot-digit-digit (e.g 12.22)
I have my work here:
public void sorting(String data) {
String[] temps = new String[200];
int cpos = 0;
int tpos = 0;
Arrays.fill(temps, null);
if (str.isEmpty() == false) {
char char1 = str.charAt(cpos);
int i = 0;
while (i < str.length()) {
char1 = str.charAt(cpos);
char1 = str.charAt(tpos);
System.out.println("the current value is " + char1 + " ");
tpos++;
if (Character.isDigit(char1)) {
temps[cpos] = "Digit";
// System.out.println(" this number is digit");
cpos++;
} else if (char1 == 'e' || char1 == 'E') {
temps[cpos] = "s_notaion";
cpos++;
} else if (char1 == '-') {
temps[cpos] = "negative";
cpos++;
} else if (char1 == '.') {
temps[cpos] = ".";
cpos++;
}
i++;
}
}
}
here is the method for floating number
private static boolean floating(String [] data) {
int count =0;
boolean correct = false;
for (int i = 0; i < data.length; i++) {
if (data[i]== "Digit" )
&& data[i]=="." && data[i]"Digit"){
// here is the problem for the condition
}
}
return false;
}
If I understood correctly, the Data array has stuff like ["Digit","Digit",".","Digit"]
So you want the
private static boolean floating(String [] data) {
method to return true if the array only has "Digit" entries and exactly one "." entry? is that it?
If so:
boolean foundLeDigit = false;
for (int i = 0; i < data.length; i++) {
if (data[i].equals("Digit") == false && data[i].equals(".") == false {
//we found something other than a Digit or . it's not a float
return false;
}
if(data[i].equals(".")) {
if(foundLeDigit) { return false; //as we found 2 "." }
foundLeDigit = true
}
}
return foundLeDigit;
The easiest way to test if a String can represent a float is to try to parse it:
String testString = "1.2345";
double result;
try {
result = Double.parseDouble(testString);
System.out.println("Success!")
}
catch (NumberFormatException nfe) {
// wasn't a double, deal with the failure in whatever way you like
}
The questions lacks a bit of context, so for my answer I'm going to presume that this is homework requiring a manual solution, and that all floating point numbers are supposed to be accepted.
Your approach (while over-engineered) is half-right: you are reducing the input string into classes of characters - digit, sign, exponent marker. What is missing is that now you have to make sure that these character classes come in the right order.
Identify the various parts of float numbers (just look at 0, -1.0, 400E30, 42.1E-30) and you'll see that they come in a specific order, even if some are optional, and that each part imposes restrictions on what characters are allowed there. For example, if there is an 'E' in the number, it has to be followed by a number (with optional sign).
So as you step through the characters of the string, think about how you could keep track of where you are in the number, and base your character validation on that (this is the state machine #JonKiparsky was mentioning).
A few small things:
Don't compare strings with '==' - use equalsTo().
Think about what it means if sorting() finds a character which is neither a digit, a sign, or the exponent 'E'?
You allocate the temps array for 200 entries, but the input string could be larger.
using the regular expression is the best way to Handel this problem
private static boolean floating(String [] data) {
int count =0;
boolean correct = false;
for (int i = 0; i < data.length; i++) {
if (str.matches("((-|\\+)?[0-9]+(\\.[0-9]+)?)+")){
System.out.println(" it's a floating number ");
correct= true;
break;
}else
correct = false;
}if (correct ==true){
return true;
}else
return false;
}

Java: Simple Recursion Issue

I'm extremely new to the whole idea of recursion, and it's blowing my mind a bit to be honest. I'm trying to turn this function I wrote into a recursive one...
public static int to_number(String s)
{
int total = 0;
int n=s.length();
for(int i = 0 ; i < n ; i++) {
char c = s.charAt(i);
if (Character.isDigit(c)){
int value=Character.getNumericValue(c);
total +=value;
}
}
System.out.println(total);
return total;
}
It reads in a string, such as "3aaa6a3", iterates through the string, if the char is a digit, it adds it to total, and so on. What I have so far...
public static int to_number(String s)
{
int total = 0;
int n=s.length();
int i=0;
if (i == n){
return 0; //if gone through the whole string
}
char c = s.charAt(i);
if (Character.isDigit(c)){
int value=Character.getNumericValue(c);
total +=value;
}
System.out.println(total);
i++;
to_number(); //trying to call the same function
return total;
}
I feel like I'm close, but just not getting it. Thanks for your time and effort!
Not gonna give you the code, but as a recursive function, you want to process the first character of the input string, then call yourself with the remaining string, i.e. to_number(s.substring(1)), and combine the result. Recursion ends when input string is empty.
try this
public void intToNum(String s, int total[])
{
if(s.isEmpty())
return;
char c = s.charAt(0);
if (Character.isDigit(c)){
int value=Character.getNumericValue(c);
total[0] +=value;
}
intToNum(s.substring(1),total);
}
and in your main, call the function as
int [] total = new int[1];
intToNum(input,total);
System.out.println(total[0]);
or another approach is
public int intToNum(String s)
{
if(s.isEmpty())
return 0;
char c = s.charAt(0);
if (Character.isDigit(c)){
int value=Character.getNumericValue(c);
return value + intToNum(s.substring(1));
}
return intToNum(s.substring(1));
}
This answer contains the solution. Just look at it when you are stuck. I also encourage you to read and understand the code instead of just copying it. This is one of the most important concepts in programming, so make sure you understand it and are familiar with it. :)
How it works: The method receives a string. If the string is longer than 1 character, the method splits it in half, calls itself on the two substrings and adds the two results. Those calls will do the same thing, until the string fragments are only 1 (or 0) characters long. In that case, it just returns their value (or 0, if there is no value).
public class RecursionVsIteration {
public static void main(String[] args) {
String str = "2.938fyfh0293urhp2398rpod8723uoihr98y";
System.out.println("Iterative: " + toNumberIterative(str));
System.out.println("Recursive: " + toNumberRecursive(str));
}
public static int toNumberIterative(String s) {
int total = 0;
int n = s.length();
for (int i = 0; i < n; i++) {
char c = s.charAt(i);
if (Character.isDigit(c)) {
int value = Character.getNumericValue(c);
total += value;
}
}
return total;
}
public static int toNumberRecursive(String s) {
int n = s.length();
// termination criteria
if (n == 0) { // emtpy string
return 0;
}
if (n == 1) { // on character string
char c = s.charAt(0);
return Character.isDigit(c) ? Character.getNumericValue(c) : 0;
}
// recursive call (split the string in half and call the method on both substrings)
return toNumberRecursive(s.substring(0, n / 2)) + toNumberRecursive(s.substring(n / 2, n));
}
}

Java: Find the longest sequential same character array

I am a new guy to java. I want to find the longest sequential same character array in a input character arrays. For example,this character array bddfDDDffkl, the longest is DDD, and this one: rttttDDddjkl, the longest is tttt.
I use the following code to deal with this problem. But, I want to improve my code, For example, if there are two same length arrays (for example rtttgHHH, there are two longest: ttt and HHH), how to solve this problem?
Thanks in advance.
My following code:
public class SeqSameChar {
public static void main (String[] args) {
int subLength = 0;
Scanner sc = new Scanner(System.in);
String[] num = null;
num = sc.nextLine().split(" ");
String[] number = new String[num.length];
for(int i = 0; i< number.length;i++) {
number[i] = String.valueOf(num[i]);
}
subLength =length(number,num.length);
System.out.println(subLength);
for(int i = index; i < index+subLength; i++) {
System.out.print(number[i]);
}
System.out.println(c==c1);
}
public static int index;
//to calculate the longest contiguous increasing sequence
public static int length(String[] A,int size){
if(size<=0)return 0;
int res=1;
int current=1;
for(int i=1;i<size;i++){
if(A[i].equals(A[i-1])){
current++;
}
else{
if(current>res){
index=i-current;
res=current;
}
current=1;
}
}
return res;
}
}
This algorithm will work perfectly fine for what you want to develop:
Before that, let me make it clear that if you want to check repeatitions of 2 different characters same number of times, you have to run a for loop in reverse to identify the 2nd character. So if the 2nd character is not same as the first one identified, and also if it's number of repeatitions are the same, you print both the characters or else, just print the single character you find at the first for loop because both the characters are going to be same.
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter String 1: ");
String A1 = sc.nextLine();
MaxRepeat(A1);
}
public static void MaxRepeat(String A) {
int count = 1;
int max1 = 1;
char mostrepeated1 = ' ';
for(int i = 0; i < A.length()-1;i++) {
char number = A.charAt(i);
if(number == A.charAt(i+1)) {
count++;
if(count>max1) {
max1 = count;
mostrepeated1 = number;
}
continue;
}
count = 1;
}
count = 1;
int max2 = 1;
char mostrepeated2 = ' ';
for(int i = A.length()-1; i>0; i--) {
char number = A.charAt(i);
if(number == A.charAt(i-1)) {
count++;
if(count>max2) {
max2 = count;
mostrepeated2 = number;
}
continue;
}
count = 1;
}
if((max1==max2) && (mostrepeated1==mostrepeated2)) {
System.out.println("Most Consecutively repeated character is: " + mostrepeated1 + " and is repeated " + max1 + " times.");
}
else if((max1==max2) && (mostrepeated1!=mostrepeated2)) {
System.out.println("Most continously repeated characters are: " + mostrepeated1 + " and " + mostrepeated2 + " and they are repeated " + max1 + " times");
}
}
I'll give you a Scala implementation for that problem.
Here it is the automatic test (in BDD style with ScalaTest)
import org.scalatest._
class RichStringSpec extends FlatSpec with MustMatchers {
"A rich string" should "find the longest run of consecutive characters" in {
import Example._
"abceedd".longestRun mustBe Set("ee", "dd")
"aeebceeedd".longestRun mustBe Set("eee")
"aaaaaaa".longestRun mustBe Set("aaaaaaa")
"abcdefgh".longestRun mustBe empty
}
}
Following is the imperative style implementation, with nested loops and mutable variables as you would normally choose to do in Java or C++:
object Example {
implicit class RichString(string: String) {
def longestRun: Set[String] = {
val chunks = mutable.Set.empty[String]
val ilen = string.length
var gmax = 0
for ((ch, curr) <- string.zipWithIndex) {
val chunk = mutable.ListBuffer(ch)
var next = curr + 1
while (next < ilen && string(next) == ch) {
chunk += string(next)
next = next + 1
}
gmax = chunk.length max gmax
if (gmax > 1) chunks += chunk.mkString
}
chunks.toSet.filter( _.length == gmax )
}
}
}
Following is a functional-style implementation, hence no variables, no loops but tail recursion with result accumulators and pattern matching to compare each character with the next one (Crazy! Isn't it?):
object Example {
implicit class RichString(string: String) {
def longestRun: Set[String] = {
def recurse(chars: String, chunk: mutable.ListBuffer[Char], chunks: mutable.Set[String]): Set[String] = {
chars.toList match {
case List(x, y, _*) if (x == y) =>
recurse(
chars.tail,
if (chunk.isEmpty) chunk ++= List(x, y) else chunk += y,
chunks
)
case Nil =>
// terminate recursion
chunks.toSet
case _ => // x != y
recurse(
chars.tail,
chunk = mutable.ListBuffer(),
chunks += chunk.mkString
)
}
}
val chunks = recurse(string, mutable.ListBuffer(), mutable.Set.empty[String])
val max = chunks.map(_.length).max
if (max > 0) chunks.filter( _.length == max ) else Set()
}
}
}
For example, for the given "aeebceeedd" string, both implementations above will build the following set of chunks (repeating characters)
Set("ee", "eee", "dd")
and they will filter those chunks having the maximum length (resulting "eee").

How could I solve this error, with my string to equation convertin calculator?

I'm writing a calculator code that solves the input whats given in string. All is good, except when it gets a negative result in the parentheses it fails badly because two operations get next to each other:
1+2*(10-11) >> 1+2*(-1) >> 1+2*-1
So where *- is, it gets "" (nothing) in the BigDecimal's constructor.
I know what's the problem, but how can I solve it?
import java.math.BigDecimal;
import java.util.ArrayList;
public class DoMath {
public static void main(String[] args) {
// Test equation goes here.
String number = "95.3+43.23*(10-11.1)";
System.out.println(doMath(number));
}
public static BigDecimal doMath(String input) {
StringBuilder builtInput = new StringBuilder(input);
StringBuilder help = new StringBuilder();
// Check if there are parenthesis in the equation.
boolean noParenthesis = true;
for (int i = 0; i < builtInput.length(); i++) {
if (builtInput.charAt(i) == 40) {
noParenthesis = false;
break;
}
}
if (noParenthesis) { // If there are no parenthesis, calculate the equation!
return calculateAndConvert(builtInput);
} else { // If there are parenthesis, breakdown to simple equations!
int parenthesePair = 0;
// Start extracting characters from the builtInput variable.
for (int i = 0; i < builtInput.length(); i++) {
// Start where we find a parentheses opener.
if (builtInput.charAt(i) == 40) {
parenthesePair = 1;
builtInput.deleteCharAt(i);
for (int j = i; j < builtInput.length(); j++) {
// If we find another opener, add one to parenthesePair variable.
if (builtInput.charAt(j) == 40) {
parenthesePair++;
}
// If we find a closer, subtract one from the given variable.
if (builtInput.charAt(j) == 41) {
parenthesePair--;
}
// If we have found the matching pair, delete it and break the for loop.
if (parenthesePair == 0) {
builtInput.deleteCharAt(j);
builtInput.insert(j, doMath(help.toString()));
break;
}
help.append(builtInput.charAt(j));
builtInput.deleteCharAt(j);
j--;
}
break;
}
}
}
System.out.println(builtInput);
return doMath(builtInput.toString());
}
public static BigDecimal calculateAndConvert(StringBuilder input) {
ArrayList<BigDecimal> listOfNumbers = new ArrayList<BigDecimal>();
StringBuilder numBay = new StringBuilder();
StringBuilder operations = new StringBuilder();
// If the first character is -, the first number is negative.
boolean firstIsNegative = false;
if (input.charAt(0) == 45) {
firstIsNegative = true;
input.deleteCharAt(0);
}
// Converting to numbers.
while (input.length() != 0) {
// If the character is a number or a dot, put it in the numBay variable and delete the char.
if (input.charAt(0) >= 48 && input.charAt(0) <= 57 || input.charAt(0) == 46) {
numBay.append(input.charAt(0));
// If the character is not a number, put it in the operations variable
// and save the number in the list (not operator characters are filtered)
} else {
listOfNumbers.add(new BigDecimal(numBay.toString()));
numBay.setLength(0);
operations.append(input.charAt(0));
}
// Delete the character.
input.deleteCharAt(0);
}
listOfNumbers.add(new BigDecimal(numBay.toString()));
// Setting first number to negative if it's needed.
if (firstIsNegative) {
listOfNumbers.set(0, listOfNumbers.get(0).negate());
}
// Calculate the result from the list and operations and return it.
return calculate(listOfNumbers, operations);
}
public static BigDecimal calculate(ArrayList<BigDecimal> list, StringBuilder ops) {
BigDecimal momentaryResult;
// Check for a multiply operation - if there is one, solve it.
for (int i = 0; i < ops.length(); i++) {
if (ops.charAt(i) == 42) {
momentaryResult = list.get(i).multiply(list.get(i + 1));
list.remove(i);
list.set(i, momentaryResult);
ops.deleteCharAt(i);
i--;
}
}
// Check for a divide operation - if there is one, solve it.
for (int i = 0; i < ops.length(); i++) {
if (ops.charAt(i) == 47) {
momentaryResult = list.get(i).divide(list.get(i + 1));
list.remove(i);
list.set(i, momentaryResult);
ops.deleteCharAt(i);
i--;
}
}
// Check for a subtract operation - if there is one, solve it.
for (int i = 0; i < ops.length(); i++) {
if (ops.charAt(i) == 45) {
momentaryResult = list.get(i).subtract(list.get(i + 1));
list.remove(i);
list.set(i, momentaryResult);
ops.deleteCharAt(i);
i--;
}
}
// Check for a plus operation - if there is one, solve it.
for (int i = 0; i < ops.length(); i++) {
if (ops.charAt(i) == 43) {
momentaryResult = list.get(i).add(list.get(i + 1));
list.remove(i);
list.set(i, momentaryResult);
ops.deleteCharAt(i);
i--;
}
}
// Return with the one remaining number that represents the result.
return list.get(0);
}
}
Edit: or would it be easier to write a new code with a different algorithm...?
I would post this as a comment to your question, but I do not have the required reputation to do so.
Anyway, since you have already recognized that the bug is the "operator" *- couldn't you make a method that would fix this problem by replacing the plus operator immediately before by a minus? Like this:
1+2*-1 >>> 1-2*1
If you want I can write you the code. But maybe it will be easier for you to adapt a solution like this in your code that is already working.
Edit - 1:
Obviously, the code should also treat the following cases:
1-2*-1 >>> 1+2*1
2*-1 >>> -2*1
Edit - 2:
Here is the code I managed to make. Let me know if you find any errors.
public int countChar(String str, char chr) {
int count = 0;
for (int k = 0; k < str.length(); k++) {
if (str.charAt(k) == chr)
count++;
}
return count;
}
public String fixBug(String eq) {
boolean hasBug = eq.contains("*-");
if (hasBug) {
String subeq;
int indbug, indp, indm;
eq = eq.replace("*-", "#");
int N = countChar(eq, '#');
for (int k = N; k > 0; k--) {
indbug = eq.indexOf('#');
subeq = eq.substring(0, indbug);
indp = subeq.lastIndexOf('+');
indm = subeq.lastIndexOf('-');
if (indp == -1 && indm == -1) {
eq = "-" + eq;
} else if (indp > indm) {
eq = eq.substring(0, indp) + '-' + eq.substring(indp + 1);
} else {
eq = eq.substring(0, indm) + '+' + eq.substring(indm + 1);
}
}
eq = eq.replace("#", "*");
}
return eq;
}

Categories