3

In PHP I have this if statement ( $first and $second will evaluate to true or false):

if ($first && $second) {
    // evereything is OK
} else {
    throw new Exception()...
}

My real code is much more complicated, I am trying to make simple example here.

I want to turn this if/else into one if with negation like this:

if (!($first && $second)){
    throw new Exception()...
}

// everything is OK

As you can see in this example, I've put ! negation sign in front of parentheses. Is this correct ? Do I need to negate every condition itself like this:

if (!$first && !$second)

Or I should use || operator:

if (!$first || !$second) // I am using OR here

I am not sure how these conditions are going to evaluate at the end, and I am confused by my dummy testing results. I really hope that someone can explain to me how all these checks are going to evaluate at the end.

Thanks to everyone who answered my question. Due to my low rep, I can not up-vote or pick some answer as the right one. You are all good for me :)

  • I would suggest !==, IMO it's easier to read... if($user !== 'john' || $status !== 'active'). Also, note the !== vs. just !=, this checks for strict equality. – neilsimp1 Jan 8 '16 at 16:38
  • @neilsimp1 you need to use an || in that to make it properly exclude his conditions. He's using an and, so if either one doesn't match then it will fall to the else - the either makes the else an or, not an and. – Jimmy Hoffa Jan 8 '16 at 16:41
  • It seems that I haven't made a good example. Let me fix it. – black-room-boy Jan 8 '16 at 16:41
  • @Jimmy ahh you're right, lemme fix that. – neilsimp1 Jan 8 '16 at 16:42
  • I have fixed example. – black-room-boy Jan 8 '16 at 16:45
17

Build a truth table:

p  q    p && q    p || q    !(p && q)    !p || !q    !(p || q)   !p && !q
==========================================================================
0  0    0         0         1            1           1           1
0  1    0         1         1            1           0           0
1  0    0         1         1            1           0           0
1  1    1         1         0            0           0           0

Thus, you see that !(p && q) is equivalent to !p || !q, but not equivalent to !p && !q. You see that !(p && q) and !p || !q are the opposite of p && q.

Note that !(p && q) and !p || !q are equivalent and can be proved by using the De Morgan's laws.

2

Yes, it should be fine. By negating the condition in the if, you're only picking up the cases that would have failed before.

Also, !($first && $second) is equivalent to (!$first || !$second), not (!$first && !$second). (Because DeMorgan's, as other answerers have mentioned).

If your results are confusing you, you could use a truth table to evaluate the expressions and find the one that fits the behavior you're looking for.

Once you have the right expression, you want to make sure you place your parentheses correctly, like ratchet freak mentioned.

These can help get you started: Truth Tables. Truth Table Generator. For the latter, you'll have to convert the operators to the ones they use.

  • and then I notice 2 other answers posted while I was typing say the same thing. Whelp.. – cbay Jan 8 '16 at 17:05
0
if (!$user == 'john' || !$status == 'active')

This does not quite do what you think it does.

If you add the brackets as the parser will add them you get:

if ( (!$user) == 'john' || (!$status) == 'active')

While you want:

if (!($user == 'john') || !($status == 'active') )

The fix to this is to add the explicit brackets or to use the not equals operator != or !== depending on if you want the identity check as well.

Besides that this is where de Morgan's laws come in.

These state that !(a||b) == (!a && !b) and that !(a&&b) == (!a || !b)

  • I have fixed example, it seems I didn't made it good so people understand. – black-room-boy Jan 8 '16 at 16:45
  • Does this mean that I can do either this if (!($first) || !($second) ) or this if (!($first) && !($second) ) ? – black-room-boy Jan 8 '16 at 16:50
  • @black-room-boy those mean different things, if you started from if (!($first && $second) ) then you have to use if (!($first) || !($second) ) – ratchet freak Jan 8 '16 at 17:06
0

As you can see in this example, I've put ! negation sign in front of parentheses. Is this correct ?

Yes, that is fine.​​​​​​​​​​​​​​​​​

Do I need to negate every condition itself like this:

if (!$first && !$second)

No, that would actually be wrong.

Or I should use || operator:

if (!$first || !$second)

Yes, that would be correct.

It would also be my personal preference of all the options you propose.

  • 1
    without an explanation, this answer may become useless in case if someone else posts an opposite opinion. For example, if someone posts a claim like "No, that is not fine...​​​​​​​​​​​​​​​​​ Yes, that would not actually be wrong... No, that would be incorrect.", how would this answer help reader to pick of two opposing opinions? Consider editing it into a better shape, to meet How to Answer guidelines – gnat Jan 8 '16 at 16:59
  • @gnat: Nobody has posted an opposite opinion. If someone disagrees with my answer, they are free to tell me why and ask for more information. For now, though, all the answers agree. This answer is a short and easy to read version that simply gives the answer to the question. Others have already gone into more depth about De Morgan's Laws. I shan't be editing this answer. Feel free to post your own answer instead of roving around schooling everybody on site usage. – Lightness Races in Orbit Jan 8 '16 at 17:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.