3

I'm terribly sorry if this is below-standard question, but I couldn't find clear answers.

As the title says, why does True and (~True) give -2 while True&(~True) gives 0? Also, Why do both of them not give False?

This is very counter-intuitive, since I expect for a single boolean expression & and and should work in the same way.

Hojin Cho
  • 384
  • 2
  • 12
  • `True and (~True)` is equivalent to just `~True`, i.e. it returns the second operand. `&` does a bitwise operation with both operands. – deceze Nov 10 '20 at 08:08
  • 1
    What is ~true do you know – Yeshwin Verma Nov 10 '20 at 08:08
  • 4
    `~` is *bitwise* negation, btw. And Python `bool` objcts are just a subclass of `int` with exactly two members, `True == 1` and `False ==0` – juanpa.arrivillaga Nov 10 '20 at 08:09
  • 2
    `&` and `~` is the bitwise operators. For boolean operators, there are `and` and **`not`**. – Dummmy Nov 10 '20 at 08:16
  • Thanks for all the comments. Right now the only question in my head is why `True` is not defined as `int(-1)`, which would've made `~True` to be `False`. – Hojin Cho Nov 10 '20 at 08:58

2 Answers2

9

True has a value of 1 in Python. Bit-inverting (~) a binary 1 (...0001) gives you ...1110. Since negative integers are represented by two's compliment, that's a value of -2.

Logical and returns its left operand if it's false, the right operand otherwise. (True is never false, obviously.)

Bitwise &, on the other hand, works on the individual bits. ...0001 & ...1110 have no 1 bits in the same position so they're all zeros in the result.


I was just surprised that a numpy array with dtype=bool acts differently with literal bool

Each Python type can implement an operator's methods with special method names. (Like .__invert__() for ~). But and, or, and not don't have these hooks, so often &, |, and ~ are used instead. For ints the implementation is bitwise, but other types can interpret operators however they want.

Note that bool is a subclass of int in Python, so it has the same operators as int. But you were operating on a numpy.ndarray, not on its individual components, so Python uses the ndarray implementation of the operators, which are not the same as bool when dtype=bool.

gilch
  • 10,813
  • 1
  • 23
  • 28
  • This is certainly not what I expected, especially considering that I deal with large numpy arrays and use `~` to negate anything, since `not` does not work on boolean arrays. Thank you for the detailed explanations. – Hojin Cho Nov 10 '20 at 08:25
  • https://numpy.org/doc/stable/reference/generated/numpy.logical_not.html – gilch Nov 10 '20 at 08:27
  • I know about it, but that's too wordy (thus leads to typos) when I write a long scripts, so I did not use it that often, and I don't think I'll use it a lot even after this fiasco... Or should I? I think it works exactly the same as `~` – Hojin Cho Nov 10 '20 at 08:38
  • Not if dtype is int. – gilch Nov 10 '20 at 08:47
  • Indeed, but I usually assign types very strictly so that's not something I'd encounter often. I was just surprised that a numpy array with `dtype=bool` acts differently with literal `bool`. – Hojin Cho Nov 10 '20 at 08:52
  • 1
    Each Python type can implement an operator's methods with [special method names](https://docs.python.org/3/reference/datamodel.html#special-method-names). (Like `.__invert__()` for `~`). But `and`, `or`, and `not` don't have these hooks, so often `&`, `|`, and `~` are used instead. For ints the implementation is bitwise, but other types can interpret operators however they want. – gilch Nov 10 '20 at 08:59
3

Remember, True == 1 and False == 0.

So,

True and (~True)

Is the same as

1 and (~1)

~ is a bitwise operation. Which kind of inverts the binary of 1. If we

print(~1)

-2

So the whole thing is simplified into

1 and -2

Which is just -2


& vs and

I expect for a single boolean expression & and and should in the same way

Dont! and is a boolean test. & Is a bitwise operation. Both of them are very different.

  • Thank you very much for the detailed explanations. I assumed somehow a `bool` type literally has, one bit. – Hojin Cho Nov 10 '20 at 08:27
  • @interjay That's right, its best not to use `&` where `and` belongs :) –  Nov 10 '20 at 08:34