-2

Okay... I want to get around the concept of computing negative numbers. I am self-learning and I am running to a lot of difficulty. How do implement negative input?

My code:

public class MainSystem {

    public static void main(String[] args) {
        try (Scanner console = new Scanner(System.in)) {
            String input;

            System.out.print(">>> ");
            input = console.nextLine();
            splitEntry(input);

            System.out.println("The console is now closed.");
        }
    }

    private static void splitEntry(String input) {

        String function = "[+\\-*/]+"; //placing them in an index
        String[] token = input.split(function);//and this
        double num1 = Double.parseDouble(token[0]);
        double num2 = Double.parseDouble(token[1]);
        //double answer;
        String operator = input.toCharArray()[token[0].length()] + "";

        if (operator.matches(function) && (token[0] + token[1] + operator).length() == input.length()) {
            System.out.println("Operation is " + operator + ", your first number is " + token[0] + " your second number is " + token[1]);
        } else {
            System.out.println("Your entry of " + input + " is invalid");
        }
        if (operator.matches(function)
                && (token[0] + token[1] + operator).length() == input.length()) {
            double result = 0;
            if (operator.equals("+")) { // this is simplified by using formatters 
                result = num1 + num2;
            } else if (operator.equals("-")) {
                result = num1 - num2;
            } else if (operator.equals("*")) {
                result = num1 * num2;
            } else if (operator.equals("/")) {
                result = num1 / num2;
            }
            System.out.printf("Your first number %.2f %s by your second number %.2f = makes for %.2f%n", num1, operator, num2,
                    result);
        }
    }
}

How do I allow my calculator to place -2 + 5 and get the answer 3?

Every time I try to do that, the program crashes? What to do to make negative numbers to be computed

GameDroids
  • 5,584
  • 6
  • 40
  • 59
Integral
  • 73
  • 2
  • 10
  • 2
    A stacktrace would help. – meskobalazs Oct 27 '14 at 15:58
  • 1
    `Why does it crashes?` It is telling you why. Maybe it is a good idea to read the stacktrace? Btw, please fix your code ... a class inside a `main` method? – Tom Oct 27 '14 at 15:58
  • 1
    you didnt get any error here `splitEntry(input);` ? `input` doest have any value. – Rustam Oct 27 '14 at 16:00
  • Read stack trace, but I could not grab the concept. It is say thing that the first error is splitEntry. – Integral Oct 27 '14 at 16:01
  • 1
    I feel like closing your question: http://stackoverflow.com/questions/12688068/how-to-read-and-understand-the-java-stack-trace – Sotirios Delimanolis Oct 27 '14 at 16:02
  • Yes, that was an error in me pasting – Integral Oct 27 '14 at 16:03
  • @Integral You may also delete this question like the old one. Create a new question if you have access to a computer, so you don't have to post code from your cell phone. This messes up the code you're posting. – Tom Oct 27 '14 at 16:04
  • 1
    Why can't you convert your tokens to Float by doing `Float num1 = new Float(token[0])`? In this case, it preserves signs and values, and also gives you the result right. – ha9u63a7 Oct 27 '14 at 16:04
  • The float did not work. How about if I creat an outer method to go through the characters in a user input that searches for -? – Integral Oct 27 '14 at 16:12
  • I did convert them and ran them through a website, but it gave me the same error. Is it the token area error? Or should I not delete the doubles when I place the floats, because that would not make any sense to me. – Integral Oct 27 '14 at 16:18
  • the problem with negative numbers in your case is that you are looking for operators in your regex (the `function` String) but you assume that only one operator will be in the middle of two numbers. e.g. `1+2` works but `-1+2` won't because `num1` looks for a Double in the array at `token[0]`. But in the case of `-1+2` the `token[0]` will be empty – GameDroids Oct 27 '14 at 16:22
  • @gamedriod, so I should delete the token [0] and token[1] and the program should run, or as hagubear suggested, making it a float instead?? – Integral Oct 27 '14 at 16:29
  • @Integral I don't think it has anything to do with `Double` or `Float`. Either you alter your regex, so it would split your expression only when an operator is in between 2 numbers (negative or not) or you access the `token` array more dynamically (maybe with a for loop, `token[i]`) and check if the value at `token[i]` is really a number you can cast – GameDroids Oct 27 '14 at 16:35
  • @GameDroids the second suggests seems ideal. How do I place it in the code? I am relatively new to programming. – Integral Oct 27 '14 at 17:52
  • @Integral let me think about it, I don't have a computer right now – sorry. But I realized that it doesn't solve the problem. It is also a question on how to get *all* operators, since a negative number would be recognized as a positive number but with an operator before. Have you thought going through the input without a regex, but each character one by one? Like: `char[] characters = input.toCharArray()` and `if(characters[i] =='+')...` ? sorry for the incomplete example. I'll try to give you a better answer, later. :) – GameDroids Oct 27 '14 at 18:03
  • Please do, @GameDroids. Pulling my hair here. – Integral Oct 27 '14 at 20:13
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/63803/discussion-between-gamedroids-and-integral). – GameDroids Oct 28 '14 at 17:02

1 Answers1

1

Ok, I think I have something. Sorry for the late answer, I hope you can still use it. First let me explain, I changed quite a lot of code.

scanning the input
the input will be read as one complete String, as in your code. But instead of splitting the code into a String[], I am 'checking' the chars one by one and try to decide whether they are an operator or a number.

If I find a number or an operator, I put it in an list instead of an array, because a list can grow dynamically and I don't know how many numbers and operators there are,yet.

private static ArrayList<String> getSequence(String input) {
    String number = "[\\d,.]+";     // RegEx to detect any number 12 or 1.2 or 1,2
    String function = "[+\\-*/]+";  // RegEx to detect any operator +-*/ 
    char[] inputChars = input.toCharArray();   // converting the input String into an array
    ArrayList<String> sequence = new ArrayList<>();  // this is the list, that will be returned
    String lastNumber = "";     // a number can consist of multiple chars, so this String is like a buffer for us where we "collect" every char until the number is complete

    for (char c : inputChars) {  // now we loop through every char in the char[]
        System.out.println("checking " + c);
        if ((new String("" + c)).matches(function)) {  // we convert our char into a String and try to match it with the "function" RegEx
            System.out.println("its an operator");
            if (!lastNumber.isEmpty()) {
                sequence.add(lastNumber); // if we detect an operator, we must check if we still have a number in our buffer. So we add the last number to our list
            }
            sequence.add("" + c);  // and we add our operator to our list
            lastNumber = "";       // we just saw an operator, so the "lastNumber" buffer should be cleared
        } else if ((new String("" + c)).matches(number)) {  // if we detect a digit/number
            System.out.println("its part of a number");
            lastNumber += c; // since this char is part of a number, we add it to the "lastNumber" buffer
            // now we need to continue, since we don't know if the number is already finished 
        }
    }
    // if we finished analyzing the char array, there might be a last number in our buffer
    if (!lastNumber.isEmpty()) {  
        sequence.add(lastNumber);  // the last number will be added too
    }
    return sequence;  // now our sequence is complete and we return it
}

So when our input would be something like 1+2+3 this method would return this list:

{"1", "+", "2", "+", "3"}

evaluating the sequence
Next we call the method evaluate(sequence) to evaluate our list. This is pretty close to your way, I just made some adjustments

 private static void evaluate(ArrayList<String> sequence) {
    double number1 = 0.0;    // the first number is also a intermediary result
    while (true) {           // we actually don't know how long the equation is, so here we have an infinite-loop. Usually not a good idea!
        try {                // we try to evaluate the next String of our sequence
            number1 = getNextNumber(sequence);  // get the next number 
            System.out.println("number1 = " + number1);
            char operator = getNextOperator(sequence);  // get the next operator
            System.out.println("operator = " + operator);
            double number2 = getNextNumber(sequence);
            System.out.println("number2 = " + number2);  // get the second number
            switch (operator) {   // I replaced your if statements with that switch (but it is actually the same)
                case '+':
                    number1 += number2;  // we add the second number to the first number and "store" the result in the first number
                    break;
                case '-':
                    number1 -= number2;
                    break;
                case '*':
                    number1 *= number2;
                    break;
                case '/':
                    number1 /= number2;
                    break;
            }
        } catch (java.lang.IndexOutOfBoundsException e) {  // here we break out of the loop. We can be 100% sure that at some point we reached the end of the list. So when we are at the end of the list and try to access the "next" element of the list (which does of course not exist) we get that IndexOutOfBoundsException and we know, we are finished here
            System.out.println("result is " + number1);
            break;  // break out of the loop
        }
    }
}

The important part here is actually that we store the result of any operation with two numbers, in the first number. So if we have 1+2+4, it will first evaluate 1+2, store the result as the first number and then evaluate 3+4

helper methods Now we still need the methods to detect either an operator or a number;

private static char getNextOperator(ArrayList<String> sequence) {
    String function = "[+\\-*/]+";   // the same regex as before to detect any operator
    // with a list it looks like this
    // list.get(0) is the same as array[0]

    if (sequence.get(0).matches(function)) {  
        return sequence.remove(0).charAt(0);  
    }
    return ' ';
}

This uses a nice trick here: sequence.get(0) will have a look at the first element in the list and return its value. But sequence.remove(0) will return its value and delete the element from the list at the same time. So the original first element will no longer be there and the previously second element becomes the first...

So first our list looks like { "-", "2"} and after calling getNextOperator() it looks like {"2"}, because we remove the operator.

And the same we do for getting the next number:

private static double getNextNumber(ArrayList<String> sequence) {
    String sign = "[+-]+";   // regex to test if a string is only a sign (+ or -)
    String number = "[\\d,.]+";  //regex to test if a String is a number (with or without . or  ,
    double number1 = 0;
    if (sequence.get(0).matches(sign) && sequence.get(1).matches(number)) {
        // first one should be a sign and the second one a number
        number1 = Double.parseDouble(sequence.remove(0) + sequence.remove(0));
    } else if (sequence.get(0).matches(number)) {
        // its a normal number
        number1 = Double.parseDouble(sequence.remove(0));
    }
    return number1;
}

Well and that's it. Now you only have to put it all together and call it in your main function like this:

public static void main(String[] args) {
    try (Scanner console = new Scanner(System.in)) {
        String input;

        System.out.print(">>> ");
        input = console.nextLine();
        ArrayList<String> sequence = getSequence(input);  // analyze input and get a list
        evaluate(sequence);  // evaluate the list
        System.out.println("The console is now closed.");
    }
}

Well, sorry for changing so much. I couldn't think of another (maybe more efficient) way to do that. This calculator is not very "smart" for now and there are a lot of things it won't handle (like letters or braces) but I hope it's a start. At least it should work with negative and positive numbers now and it should be able to handle even longer equations.

cheers!

GameDroids
  • 5,584
  • 6
  • 40
  • 59
  • Lots of new concepts in it that i do not not know that well, but i guess i better get to studying the, Thanks. – Integral Oct 28 '14 at 04:06
  • If there is something in this answer you don't understanf, please don't hesitate to ask. With you calculator you have a very interesting project, but it is also quite difficult :) – GameDroids Oct 28 '14 at 09:55
  • I have changed my entire code yet again. I need your help, again! – Integral Oct 28 '14 at 16:56
  • @Integral Sure, if you have a question that is not related to this one, just open a new question and post your changed code there. – GameDroids Oct 28 '14 at 17:02
  • @Integral I also opened a chat on StackOverflow [here](http://chat.stackoverflow.com/rooms/63803/discussion-between-gamedroids-and-integral) if you want. So we won't need to use the comments all the time – GameDroids Oct 28 '14 at 17:04