PalmfrondJohn
PalmfrondJohn

Reputation: 83

Boolean test case failing when it should pass

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

Answers (7)

user2336315
user2336315

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 :

  • If negative is 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.
  • If negative is 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

Peter Lawrey
Peter Lawrey

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

nachokk
nachokk

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

Martijn Courteaux
Martijn Courteaux

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

Kejne
Kejne

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

peter.petrov
peter.petrov

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

T.J. Crowder
T.J. Crowder

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

Related Questions