If-else statements, always running - java

I am working on making a coffee ordering system. It takes inputs from users and calculates the price of their coffee. One of the inputs asked for is "syrupshots". This code always makes syrupshots = 3 even if the user properly chose a number according to the size of their coffee.
//if size == tall syrup shots <=3
if(size == 1 && syrupshots < 1 || syrupshots > 3)
{
syrupshots = 3;
}
//else if size == medium syrup shots <=5
else if(size == 2 && syrupshots < 1 || syrupshots > 5)
{
syrupshots = 3;
}
//else if size == Venti syrup shots <=7
else if(size == 3 && syrupshots < 1 || syrupshots > 7)
{
syrupshots = 3;
}
System.out.println(syrupshots);
I am not sure why syrupshots is always = 3 no matter what.

Not always, sometimes it returns 1 or 2. But never >3, like it looks like it should.
Your problem is with logical operator precedence. For example:
if(size == 1 && syrupshots < 1 || syrupshots > 3) {}
If size=3 and syrupshots=5 (a valid combination), then this if block is still entered because the && is evaluated first:
size == 1 && syrupshots < 1
and that equals false, so you have left (false || syrupshots > 3)
BUT then the || is evaluated, syrupshots > 3 is true, so the whole expression is true
You need to change the order of precedence by using brackets:
if(size == 1 && (syrupshots < 1 || syrupshots > 3)) {}

As one comment says, all conditions trigger syrupshots to be assigned three. Also, I don't think you wrote your test condiiotns correctly, judging from your comments.
if(size == 1 && syrupshots <= 3)
^That would be proper way to test for the check outlined in your comment

Related

Java while(condition doesn't reach)?? Why

Why is it when I do this
while(word.charAt(left) == word.charAt(right) && left >= 0 && right < word.length()){
left--;
right++;
}
its says in the while conditions "left >= 0 && right < word.length()" condition doesn't reach, but when I do it like this
while(left >= 0 && right < word.length() && word.charAt(left) == word.charAt(right)){
left--;
right++;
}
The conditions are met.
Is there an order for while(loop conditions)???
The order does matter as conditions are checked from left to right. You're getting that message because if the previous condition evaluates to true, then those two conditions
left >= 0 && right < word.length()
will always evaluate to true. You probably want the latter (since you would want to check all the conditions).

JAVA How will an IF statement evaluate if || (OR) as well as && (AND) are placed in the same if statement

Currently I am working on a little personal project to help myself learn about coding.
I'm wondering for future reference if I can combine logical operators of different types in a single if statement.
For example if I had
if (n == 0 || n == 1 && m == 0 || m == 1) {
doSomething();
}
Would it check if either parts of the left side are true, then if either parts of the right are true, or would it do something similar to checking if both of the middle ones are true?
Does using parenthesis change anything
For example
if ((n == 0 || n == 1) && (m == 0 || m == 1)) {
doSomething();
}
Edit:
From a suggestion I tried it out, but when i put three variables it started acting weird
Here's my test:
int n = 1;
int m = 1;
int o = 1;
if (n == 0 || n == 1 && m == 0 || m == 1 && o == 0 || o == 1) {
System.out.println("True");
}
else {
System.out.println("False");
}
if ((n == 0 || n == 1) && (m == 0 || m == 1) && (o == 0 || o == 1)) {
System.out.println("True");
}
else {
System.out.println("False");
}
if all of them are 1 or 0, they both evaluate true, if n or m is not 1 or 0 the top evaluates true but the bottom does not.
However if o is not 0 or 1 both of them are false.
I have found that parenthesis do in fact make a difference, but I can't quite tell why it's acting the way it is.
&& has a higher precedence then ||, so n == 0 || n == 1 && m == 0 || m == 1 equals n == 0 || (n == 1 && m == 0) || m == 1. You may check the precedence table here.

Order of Operations with Logic in Java Confused

I have an order of operations problem from a quiz and the explanation is not exactly helpful. Here is the code:
package com.udayan.oca;
public class Test {
public static void main(String [] args) {
int a = 2;
boolean res = false;
res = a++ == 2 || --a == 2 && --a == 2;
System.out.println(a);
}
}
It says it prints 3 which it does because I tested that but I do not understand how. Here is their explanation:
a++ == 2 || --a == 2 && --a == 2;
[Given expression]. (a++) == 2 || --a == 2 && --a == 2;
[Postfix has got higher precedence than other operators].
(a++) == 2 || (--a) == 2 && (--a) == 2;
[After postfix, precedence is given to prefix].
((a++) == 2) || ((--a) == 2) && ((--a) == 2);
[== has higher precedence over && and ||].
((a++) == 2) || (((--a) == 2) && ((--a) == 2));
[&& has higher precedence over ||].
Let's start solving it: ((a++) == 2) || (((--a) == 2) && ((--a) == 2));
[a=2, res=false].
(2 == 2) || (((--a) == 2) && ((--a) == 2));
[a=3, res=false]. true || (((--a) == 2) && ((--a) == 2));
[a=3, res=false].
|| is a short-circuit operator, hence no need to evaluate expression on the right.
res is true and a is 3.
Yes, I understand short circuiting by the way so no need to explain that.
So here is my thinking however:
res = a++ == 2 || --a == 2 && --a == 2 ->
(((a++) == 2) || (((--a) == 2) && ((--a) == 2))) [a = 2]
(((a++) == 2) || ((**1** == 2) && ((--a) == 2))) [a = 1]
(((a++) == 2) || (**false** && (**0** == 2))) [a = 1] //short-circuits
(((a++) == 2) || **false**) [a = 1] //short circuits
(**false**) [a = 1]
????
Another point is that the answer key says to do a++ first then || next. a++ yah that makes sense. But I thought && is before ||.
From the Java Language Specification,
The conditional-or operator || operator is like | (ยง15.22.2), but evaluates its right-hand operand only if the value of its left-hand operand is false.
So, this is simpler than you think. res = a++ == 2 || --a == 2 && --a == 2; is evaluated like so:
res = ((a++ == 2) || ((--a == 2) && (--a == 2)));
a++ == 2? Post-increment means that a is read as 2. Then that expression is evaluated. 2 == 2, which is true. Short circuit means that the rest of the expression is never evaluated.
So, essentially all the above code does is res = a++ == 2;
I made a simple program to test this:
public class TestSOCode {
public static void main(String [] args) {
test1();
}
private static void test1(){
int a = 2;
boolean res = false;
//res = a++ == 2 || --a == 2 && --a == 2;
res = expression(a++, "One") || expression(--a, "Two") && expression(--a, "Three");
System.out.println(res +" "+ a);
}
private static boolean expression(int i, String s){
System.out.println(s+ " called with "+ i);
return i == 2;
}
}
This gives the result
One called with 2
true 3
UPDATE: After some discussion and research, I think there's been a misunderstanding of the difference between precedence and execution order when it comes to logical operators.
res = a++ == 2 || --a == 2 && --a == 2;
The above statement's precedence is worked out before it's evaluated. I won't go over the other precedence rules since it would complicate this answer, so I'll simplify it:
res = x || y && z;
&& takes precedence, so the expressions are grouped together like so:
res = x || (y && z);
As we can see, && takes priority, so the expressions to it's left and right are grouped together, then || is evalutated. The expression to it's left is x and the expression on it's right is (y && z) (I think we were both thinking that if && took priority, it would be like (a || b) && c so it would be evaluated first, but that's not how it works). If we want to see that this is in fact the case, we can modify the above code like so:
res = expression(a = 8, "One") || expression(a = 16, "Two") && expression(a = 32, "Three");
This is equivalent to false || (false && false), but without any compiler interference with compile-time constants. The result of this is:
One called with 8
Two called with 16
false 16
First, the || is evaluated, then the left side of the &&. This returns false, and false && ? will always be false, so the third expression is not evaluated. But no precedence rules have been violated. I hope this has cleared up any confusion. If not, I'm happy to continue discussion in chat and update my answer. Because we know from the original code that if the first expression is true, the || returns true and short-circuits, we can say that a || b && c is not grouped together into (a || b) && c.
res = a++ == 2 || --a == 2 && --a == 2 (res is true)
1. a++ (post-increment, no) -> a = a + 1 -> it's still 2 -> when true -> it becomes 3
2. --a (pre-increment, right to left) -> a - 1 = a -> 1
3. --a (pre-increment, right to left) -> a - 1 = a -> 0 (its because of logical and, it never execute this part)
4. == (equality, left to right) -> 2 == 2 || 1 == 2 && 0 == 2 -> true || false && false
5. && (logical and, left to right) -> false -> no more steps
6. || (logical or, left to right) -> true -> go to 1.
// so take 3
// moral of the story is always use paranthesis
// op is correct for short-circuit
In the end when(((a++) == 2) || false) [a = 1]
Is done then as the || operator having less precedence than ++ so here a will become 3 .. then it will print a=3
Though it's a short circuit operator still it have to do the ++ operator 1st.

multiple conditions else / if statement somehow wrong?

I'm doing a hackernet challenge where n is an int input. The conditions are:
If n is odd, print Weird
If n is even and in the inclusive range of 2 to 5, print Not Weird
If n is even and in the inclusive range of 6 to 20, print Weird
If n is even and greater than 20, print Not Weird.
Im sure the code makes logic and dont think theres syntax. It gives the correct responses and hackernet still says its incorrect so ive come here to see if anyone can see what the problem is
public static void main(String[] args)
{
int N = scanner.nextInt();
scanner.skip("(\r\n|[\n\r\u2028\u2029\u0085])?");
if (N % 2 != 0 || N % 2 == 0 && N >= 6 && N <= 20)
{
System.out.print("weird");
}
else
{
System.out.print("not weird");
}
}
The problem is the logic in your else condition, which would also catch values of N which are less than 2. Try this version:
if (N % 2 != 0)
{
System.out.print("weird");
}
else if (N >= 2 && N <= 5 || N > 20)
{
System.out.print("not weird");
}
else if (N >= 6 && N <= 20)
{
System.out.print("weird");
}
else
{
// NOTE: if the code still fails, remove this else condition
System.out.print("unexpected value of N");
}
Note: To get your code to pass the Hackernet task, you might have to completely remove the else condition. I added it for completeness, but Hackernet might test N=1 to see if nothing gets printed.
Read this condition :
if (N % 2 != 0 || N % 2 == 0 && N >= 6 && N <= 20)
as
if (N % 2 != 0 || (N % 2 == 0 && N >= 6 && N <= 20))
Then see how operator precedence changes the behaviour and yield desired results.
Check the following one
public static void main(String[] args)
{
int N = scanner.nextInt();
scanner.skip("(\r\n|[\n\r\u2028\u2029\u0085])?");
if(N%2!=0) {
System.out.print("weird");
}else if(N>=2 && N<=5) {
System.out.print("not weird");
}else if(N>=6 && N<=20) {
System.out.print("weird");
}else if(N>20) {
System.out.print("not weird");
}
}
For the technical part: start by reading about
precedence of java operators and then make your code easier to read.
Pushing that many conditions into a single if is not helpful. You see it yourself: you think the code is correct, but probably it isn't. And now you look to other people to explain your overly complex code back to you. And of course, all the other answers do all that for you ... but beyond that:
The "real" answer here is: learn how to test your code.
Instead of having a main that somehow asks for a number, and then makes decisions, write a method boolean isWeird() that takes a number and returns true/false according to your requirements.
And then simply test that method with all reasonable cases. And then check if that result is as expected.
Using JUnit, you could write something like
assertThat(isWeird(1), true);
assertThat(isWeird(21), true);
assertThat(isWeird(22), true);
...
Ideally, you write such tests before you implement that method. And then you implement all the conditions, and any check that fails tells you that you got something wrong.
I feel, In the if (N % 2 != 0 || N % 2 == 0 && N >= 6 && N <= 20) condition, you are verifiying the odd and even values at same time using && and || operator. Can you modify the condition into like this if (N % 2 != 0 || (N % 2 == 0 && N >= 6 && N <= 20)) and check? If N is odd weird will be printed or if N is even and it falls under the 6 and 20 inclusive, weird will be printed.
You already have a good few answers here but if you think logically about what you actually need, you can break it down easier.
It looks like the only "Not Weird" print out is 2, 4 and even numbers > 20
So an example could be something like:
if (n % 2 == 0) {
if ((n >= 2 && n <= 5) || (n > 20)) {
return "Not Weird";
}
}
return "Weird";
You can try this
private static final Scanner scanner = new Scanner(System.in);
public static void main(String[] args) {
int n = scanner.nextInt();
scanner.skip("(\r\n|[\n\r\u2028\u2029\u0085])?");
if (n % 2 == 1 || (n >= 6 && n <= 20)) {
System.out.println("Weird");
} else {
System.out.println("Not Weird");
}
scanner.close();
}

How can I make this stopping criteria effective?

I dont know why this stopping criteria keeps failing but I believe it has something to do with the logical or (||). I debugged and it doesnt seem to stop where I want it to, which is on when cp (current position) is on the perimeter of the array.
if(cp == start || (cp.getColumn() > 0 || cp.getColumn() < maze[0].length-1 || cp.getRow() > 0 || cp.getRow() < maze.length+1)){`
This is a for a maze solving algorithm. Basically, the maze is a 2D array made up of X's for walls. Every cell with an X is a wall and the 'current position' can not access it. The mission of the 'current position' is to get to out of the maze which means it either has to be in the first or last column or first of last row. The algorithm works very well but just doesn't recognize when the current position is at the index of the exit.
I'm sorry for being so vague, I've been working on this for so long...
So, none of the following things is true:
cp == start
cp.getColumn() > 0
cp.getColumn() < maze[0].length - 1
cp.getRow() > 0
cp.getRow() < maze.length + 1
But you think (at least) one of them should be true. Which one?
Being or statements, that extra set of parentheses are redundant:
if(cp == start || cp.getColumn() > 0 || cp.getColumn() < maze[0].length-1 || cp.getRow() > 0 || cp.getRow() < maze.length+1){
I can't see exactly what you are doing, but I hope this helps at least...
I con't really see what you're trying to do here, but guessing that 'maze' is a two dimensional array, it should probably be maze.length-1 in the last comparison. However, this would make the if statement evaluate to true when cp is NOT on the perimeter of the array.
It appears you are using the start conditions in your OR set. You may want to put an ! (Not) before the first bracket. As written, I think the else clause would be where your stop should occur.
Consider wrapping the processing code in this if statement.
Desk check your logic to see when you exit. Remember that OR stops processing on the first TRUE, and AND stop processing on the first FALSE.
I'm not sure you've copied your code correctly
if(cp == start
|| (cp.getColumn() > 0 || cp.getColumn() < maze[0].length-1
|| cp.getRow() > 0 || cp.getRow() < maze.length+1)) {
For simplicity of understanding pretend that maze.length[0]-1 evaluates to, say 3, then consider this bit:
cp.getColumn() > 0 || cp.getColumn() < 3
That will be true for every value of the cp.getColumn(), try say 8, yep, bigger than 0, -99, yep it's less than 3. I'll bet you meant
cp.getColumn() > 0 && cp.getColumn() < 3
this will be true if the column is in the maze. If you want to test for out of the maze:
cp.getColumn() <= 0 || cp.getColumn() >= 3
(Side note I use <= 3, not just == 3 deliberately, this deals with cases such as move of more than one step.)
If you want to test if it's in the maze you have
if(cp == start
|| (
cp.getColumn() > 0 && cp.getColumn() < columnCount
&& cp.getRow() > 0 && cp.getRow() < rowCount)) {
if you want to test if it's outside the maze
if(cp != start
&& (
cp.getColumn() <= 0 || cp.getColumn() >= columnCount
|| cp.getRow() <= 0 || cp.getRow() >= rowCount)) {

Categories