3

I'm translating this from C to Python:

int_fast16_t x;
int_fast16_t y = compute_value();
x = ~y;
y = x+1;

I don't think

y = compute_value()
y = (~y) + 1

will work: how would it know on how many bits should the binary NOT be done? (8? 16? 32?).

In the case of C, it is explicit with the type int_fast16_t, but with Python we don't know a number of bits in advance.

How do you do this in Python?

I have read How do I do a bitwise Not operation in Python? but here it's more specific: how does Python infer the number of bits to use in a binary NOT?

Example:

How does Python know if the binary NOT of 3 (0b11) should be done on 4 bits: 0b00 or on 8 bits: 0b11111100 or on 16 bits: 0b1111111111111100?

Basj
  • 41,386
  • 99
  • 383
  • 673
  • 1
    This should work fine, though you can `& 0xffff` the result to clamp it if you want to be safe. Also, those two steps are equivalent to `x=-x` since python always uses 2's complement. – dbush May 31 '22 at 15:55
  • @dbush Thanks, but how does Python know if binary NOT of 3 (`0b11`) should be done on 4 bits: `0b00` or on 8 bits: `0b11111100` or on 16 bits: `0b1111111111111100`? – Basj May 31 '22 at 16:05
  • 2
    @Basj Just as positive numbers implicitly have an infinite number of high-order zero bits, negative numbers implicitly have an infinite number of high-order 1 bits. – Barmar May 31 '22 at 16:29
  • @Barmar This is a good visual way to understand this! You should post it as an answer. – Basj May 31 '22 at 19:18

2 Answers2

3

Python int has an infinite number of bits. The only way to invert them all is to negate the sign of the number. So for example ~1 is -2. To get a specific number of bits in the result, you have to mask off those bits. (~1)&0xffff is 0xfffe which is one bit off, I assume due to two's complement.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • could you also use `.bit_length()` to get the number of bits? for example: `a=1; (~a).bit_length()` – jkr May 31 '22 at 16:26
  • 1
    @jakub That still requires Python to calculate `~a` first, so it needs to determine how many bits it requires. – Barmar May 31 '22 at 16:27
  • @Barmar it just inverts all the bits it has stored and doesn't worry about the rest, I assume. I haven't checked the source to see what it actually does, if someone else did that would make an even better answer. – Mark Ransom May 31 '22 at 16:56
  • if it helps, here is the [code for inverting and integer](https://github.com/python/cpython/blob/eb618d5ff0371efead28a3afa91834e4beebf73d/Objects/longobject.c#L4615-L4629) and the [code for `int.bit_length()`](https://github.com/python/cpython/blob/854db1a6061c83d80a3f1e4e87f043b521719920/Objects/longobject.c#L5624-L5686) – jkr May 31 '22 at 17:30
1

how does Python infer the number of bits to use in a binary NOT?

It uses all bits in the binary representation it has for the operand. Python integers consist of one or more longs (see Python integer objects).

How does Python know if the binary NOT of 3 (0b11) should be done on 4 bits: 0b00 or on 8 bits: 0b11111100 or on 16 bits: 0b1111111111111100?

There is no case where it would be just 4 or 8 bits. It is done on all bits in the 64 bits it has for the integer (or a multiple of that, if the original value needed more long words).

trincot
  • 317,000
  • 35
  • 244
  • 286