-2

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.
}
Omer Hen
  • 13
  • 6
  • Please show example inputs and outputs for the unexpected results you are seeing – Easton Bornemeier Aug 03 '17 at 05:04
  • can you please provide formats of str and function Strings? – sAm Aug 03 '17 at 05:05
  • 2
    So it's "gone wrong", it's "a little off", there's "a strange bug", it "gets weird" and "things get messy"? That shouldn't be too hard to diagnose. – m69's been on strike for years Aug 03 '17 at 05:07
  • The strings themselves don't have independent functions, they're coming from a pre-existing textfield. I just use (textField_name).getText() store it in a String variable. @sAm – Omer Hen Aug 03 '17 at 05:13
  • It's more than just a debugger question, there's a problem with the logic of my algorithm... @Andreas – Omer Hen Aug 03 '17 at 05:16
  • Please give us a specific example of an input that gives a wrong result. Otherwise, it's impossible for any of us to work out what's going on. – Dawood ibn Kareem Aug 03 '17 at 05:17
  • 745 + 632 = 137732 741 + 321 = 106221 963 - 852 = 11152 951 - 357 = 59457 Those are just some random examples of three digit numbers. It's essentially any three digit number +/-/*/divided another. Somtimes its even two digit numbers, but I can't find a pattern in which numbers the calculation works, and in which it doesn't. @DawoodibnKareem – Omer Hen Aug 03 '17 at 05:18
  • OK, and what is `strSort`? – Dawood ibn Kareem Aug 03 '17 at 05:18
  • Incidentally, when I pass "745 + 632" and "+" to your method, OperationResult comes out to 108. – Dawood ibn Kareem Aug 03 '17 at 05:23
  • strSort is a function that distinguishes between ints and doubles, so after the calculation's been done, instead of int numbers presented with a decimal point, they're presented as ints. For example, if I had this number: 32.0, I don't want the .0 to be there so the strSort does that .. – Omer Hen Aug 03 '17 at 05:23
  • Well, your first error is that in the lines where you assign `firstValue` and `secondValue`, your `substring` operations have the wrong indexes. So for example, with my input of `745 + 632`, you're finding `str.substring(1, 3)` (which is 45) and `str.substring(6,8)` (which is 63). You need to get rid of the `+1` after `closestDown` and the `-1` after `closestUp`. – Dawood ibn Kareem Aug 03 '17 at 05:35
  • I suspect from the outputs you've shown that you have a similar error in `strSort`. I don't know why you haven't shown us that method. – Dawood ibn Kareem Aug 03 '17 at 05:36
  • @Andreas if you dupehammer every question that could be resolved with the help of a debugger, there won't be much left on Stack Overflow. I don't think you've done the right thing here - there are far worse questions than this one out there. – Dawood ibn Kareem Aug 03 '17 at 05:38
  • Just posted the strSort method @DawoodibnKareem Your answer helped, but now there's an error in the strSort method. BTW, the result parameter refers to the OperationResult variable. – Omer Hen Aug 03 '17 at 05:51
  • OK, do NOT use `str.replace` the way you have. It replaces **every** occurrence of a string with the replacement. Seriously, why don't you just build a new string with the content you need, rather than messing round with substrings and replacements? This code is practically impossible to understand - you've gone about this entirely the wrong way. – Dawood ibn Kareem Aug 03 '17 at 05:56
  • Alright yea I did it kinda quickly.. I'll remake the strSort method in a better way. But is the basicEval fine? or should I remake it too? @DawoodibnKareem I mean I'll build it on the same concept, just in a more professional way now that I have time. – Omer Hen Aug 03 '17 at 06:00
  • Well ... it's really not how I'd write it. But if you can make it work, then great. – Dawood ibn Kareem Aug 03 '17 at 06:04
  • @DawoodibnKareem Ok, I've removed the duplicate, but this question is really a "debug this code for me" question, and is off-topic for StackOverflow. If OP simply stepped thru the code with a debugger, a simple look at the intermediate values would show where things are "a little off", and it could be fixed. That is OPs job to do, not is not a valid question for SO. – Andreas Aug 03 '17 at 14:33
  • You're asking yourself why you get the error code? Since you never modify that variable in the function, ask yourself why the calling method passes an string different to your operators... Also your for loop's comments seem to indicate that it's supposed to do the work of `String.indexOf` and `String.lastIndexOf` (with starting index specified) - why reinvent the wheel instead of using those existing methods? – fabian Aug 03 '17 at 15:23
  • Fixed it, look at my answer. Thanks for everything !! @DawoodibnKareem – Omer Hen Aug 03 '17 at 16:36
  • It's these kinds of questions that give the math tag a bad name. It's not a math problem; this is simple arithmetic and poor debugging skills. – duffymo Aug 03 '17 at 19:32
  • Bro you do realize that I wasn't complaining about the math in Java right? @duffymo I needed help with my algorithm, nothing more.. – Omer Hen Aug 03 '17 at 19:41
  • I'm not your bro. I know what you were asking. It's not even about math, because this is arithmetic. It's about the inability to debug. – duffymo Aug 03 '17 at 19:42

1 Answers1

-1

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 !!

Omer Hen
  • 13
  • 6