[Tutor] reverse diagonal

eryksun eryksun at gmail.com
Mon Dec 3 05:35:33 CET 2012


On Sun, Dec 2, 2012 at 2:32 AM, Steven D'Aprano <steve at pearwood.info> wrote:
>
>> ~i returns the value (-i - 1):
>
> Assuming certain implementation details about how integers are stored,
> namely that they are two-compliment rather than one-compliment or
> something more exotic.

Yes, the result is platform dependent, at least for the 2.x int type.
I saw it in someone else's code or blog a while ago and thought I'd
pass it along as a novelty and something to keep an eye out for.

A multiprecision long might qualify as exotic. It uses sign-magnitude
form. The sign of the number and the length of ob_digit are both
stored in ob_size. For the invert op, it adds 1 and negates the sign
to emulate 2's complement:

http://hg.python.org/cpython/file/70274d53c1dd/Objects/longobject.c#l3566

Further along is more 2's complement emulation for bitwise &, |, and ^:

http://hg.python.org/cpython/file/70274d53c1dd/Objects/longobject.c#l3743

> Okay, just about every computer made since 1960 uses two-compliment
> integers, but still, the effect of ~i depends on the way integers are
> represented internally rather than some property of integers as an
> abstract number. That makes it a code smell.

It relies on integer modulo arithmetic. The internal base is arbitrary
and not apparent. It could be 10s complement on some hypothetical base
10 computer. In terms of a Python sequence, you could use unsigned
indices such as [0,1,2,3,4,5,6,7] or the N=8 complement indices
[0,1,2,3,-4,-3,-2,-1], where -1 % 8 == 7, and so on. The invert op can
be generalized as N-1-i for any N-length window on the integers (e.g.
5-digit base 10, where N=10**5, subtract i from N-1 == 99999), which
just inverts the sequence order. The interpretation of this as
negative number depends on a signed type that represents negative
values as modulo N. That's common because it's a simple shift of the
window to be symmetric about 0 (well, almost symmetric for even N);
the modulo arithmetic is easy and there's no negative 0. However, with
a multiprecision integer type, it's simpler to use a sign magnitude
representation.

That said, I don't want to give the impression that I disagree with
you. You're right that it isn't generally advisable to use a single
operation instead of two or three if it sacrifices clarity and
portability. It didn't jump out at me as a problem since I take 2s
complement for granted and have a bias to favor symmetry and
minimalism.


More information about the Tutor mailing list