This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author ncoghlan
Recipients CuriousLearner, docs@python, mark.dickinson, ncoghlan, wolma
Date 2017-05-16.12:59:20
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1494939561.98.0.153650750258.issue29710@psf.upfronthosting.co.za>
In-reply-to
Content
I think the simplest fix to make the docs "not wrong" would be to just delete the part in parentheses.

Beyond that, I'm not quite sure how to concisely describe the actual behaviour, but I think the mention of "2's complement" isn't especially helpful in its current form, since we don't give a clear sense of how the translation from an arbitrary length integer to a suitable 2's complement form is handled.

For `~n`, the most concise explanation is the arithmetic equivalent: it is always implemented as `-(n+1)`

Similarly, for `x << n` and `x >> n`, they're now exactly equivalent to `x * 2 ** n` and `x // 2 ** n` without any overflow checking or internal representation qualification (as even in Python 2.x, left-shift will automatically promote to a long when needed)

For `x | y` and `x & y`, things are a little more subtle, since that's where the internal 2's complement representation comes into play, but you can't just write out the formal definition of 2's complement at the Python level and get the same answer as is given by the binary operators:

>>> -5 & 5
1
>>> -5 | 5
-1

>>> (~-5 + 1) & 5 # Effectively '5 & 5'
5
>>> (~-5 + 1) | 5 # Effectively '5 | 5'
5

>>> -5 | (~5+1) # Effectively '-5 & -5'
-5
>>> -5 & (~5+1) # Effectively '-5 | -5'
-5


The problem here is that the sign bits of the operands matter a great deal, since they affect the sign expansion in the conversion to the 2's complement form, but that detail gets lost if the conversion is done prior to the bitwise binary operator invocation.

One way to get the same results as the interpreter level algorithms is to use a 2's complement bit length of `1 + max(x.bit_length(), y.bit_length()`, so the equivalent operations become:

>>> bin(0b1011 & 0b0101) # -5 & 5 -> 1 in 4 bit 2's complement
'0b1'
>>> bin(0b1011 | 0b0101) # -5 | 5 -> -1 in 4 bit 2's complement
'0b1111'

So perhaps a helpful change to make would be to move the note about negative numbers to a numbered footnote in the table, and state that the bitwise binary operations are semantically equivalent to calculations using two's complement in a bit-width of `1 + max(x.bit_length(), y.bit_length()`.
History
Date User Action Args
2017-05-16 12:59:22ncoghlansetrecipients: + ncoghlan, mark.dickinson, docs@python, wolma, CuriousLearner
2017-05-16 12:59:21ncoghlansetmessageid: <1494939561.98.0.153650750258.issue29710@psf.upfronthosting.co.za>
2017-05-16 12:59:21ncoghlanlinkissue29710 messages
2017-05-16 12:59:20ncoghlancreate