Reputation: 83
I am refreshing myself with some Java practice problems to help teach some friends of mine how to code and, embarrassingly enough, I am failing a single test case on a seemingly easy test case and can't see what I am doing wrong. The practice question is:
Given 2 int values, return true if one is negative and one is positive. Except if the parameter negative
is true, then return true only if both are negative.
My code is:
public boolean posNeg(int a, int b, boolean negative) {
if(negative == true && (a < 0 && b < 0))
return true;
else if(negative == false && (a < 0 && b > 0) || (a > 0 && b < 0))
return true;
return false;
}
And the test case is: posNeg(1, -1, true)
-> false (My output is true which is incorrect.)
Upvotes: 1
Views: 604
Reputation: 16067
You can do this way too :
public boolean posNeg(int a, int b, boolean negative) {
int a1 = Integer.numberOfLeadingZeros(a);
int b1 = Integer.numberOfLeadingZeros(b);
return negative ? (a1 + b1) == 0 : ((a1 & b1) == 0 && (a1 != b1));
}
Explanation :
true
, you want to return true if both numbers are negative so it implies that the left most bit of both number are a 1, so numberOfLeadingZeros
will return 0 for both.false
, then if (a1 & b1 == 0)
, that means that one of the numbers is negative, but it can also means that both are negative, so you have to check that a1 != b1
.Upvotes: 1
Reputation: 533870
A shorter version is
public boolean posNeg(int a, int b, boolean negative) {
return (negative ? a & b : a ^ b) < 0;
}
This works because a & b
is negative iff both are negative and a ^ b
is negative iff one, and only one is negative.
If you used int
with 0 = false and 1 = true instead of boolean as C (and byte code) does you could write
public int posNeg(int a, int b, int neg) {
return (neg * (a & b) + (1 - neg) * (a ^ b)) >>> -1;
}
One trick here is that >>> -1
gives you the top bit as 0 or 1 for both int
and long
.
Upvotes: 3
Reputation: 14413
Your output is ok, you should change
if( negative == false && (a < 0 && b > 0) || (a > 0 && b < 0))
to
if( !negative && ( (a < 0 && b > 0) || (a > 0 && b < 0) ) )
^ ^
&&
works like multiplication
If you have this
negative == false && (a < 0 && b > 0) || (a > 0 && b < 0)
is like
( negative == false && (a < 0 && b > 0) ) || (a > 0 && b < 0)
^ ^
Upvotes: 2
Reputation: 68907
public boolean posNeg(int a, int b, boolean negative)
{
if(negative)
{
return a < 0 && b < 0;
} else
{
return (long) a * b < 0;
}
}
This is translated what you said. Note the smart way of checking if only one is negative:
- * -
= +
- * +
= -
+ * -
= -
+ * +
= +
But as @peter.petrov pointed out: this might overflow if your integers are too big. That is why the cast to the long is required. So a better nice way to check this is to do:
(a < 0) ^ (b < 0)
Which makes a nice one-liner, using the ternary conditional operator:
public static boolean posNeg(int a, int b, boolean negative)
{
return negative ? a < 0 && b < 0 : ((a < 0) ^ (b < 0));
}
Upvotes: 1
Reputation: 24
The problem seems to lie in the row:
else if(negative == false && (a < 0 && b > 0) || (a > 0 && b < 0))
you're writing (false AND false OR true), so the OR case is evaluated to true, thus entering the if-statement. try writing it like this instead:
else if (!negative && ((a < 0 && b > 0 ) || (a > 0 && b < 0)))
that is: (false AND (false OR true)), evaluating the negative flag each time
Upvotes: 1
Reputation: 39477
Try simplifying it like this.
public boolean posNeg(int a, int b, boolean negative) {
if (negative) return a < 0 && b < 0;
else return 1L * a * b < 0L;
}
Upvotes: 2
Reputation: 1075597
This is the culprit:
else if(negative == false && (a < 0 && b > 0) || (a > 0 && b < 0))
That breaks down into:
else if(
negative == false && (a < 0 && b > 0)
||
(a > 0 && b < 0)
)
E.g., it doesn't care about the value of negative
if the condition after the ||
is true, it follows the path and returns true
.
You probably want parens in there somewhere. I haven't fully worked through your logic, but possibly you meant:
else if(
negative == false && (
(a < 0 && b > 0)
||
(a > 0 && b < 0)
)
)
Upvotes: 1