long int behaviour

Tim Peters tim.one at home.com
Thu Mar 1 00:09:25 EST 2001


[Timothy Grant]
> ...
> Given the following experimenting...
>
> >>> hex(4294965248L)
> '0xFFFFF800L'
> >>> hex(~4294965248L)
> '-0xFFFFF801L'
> >>>
>
> The first output is what I would expect, however, I would have
> expected the second output to be
>
> 0x000007FFL
>
> It appears to be something to do with two's complement storage,
> but I'm at a loss as to why my expectations were so incorrect.

Take heart!  Your expectations weren't born incorrect, they were made
incorrect, by a world of evil languages promulgating their blasphemous
treachery that integers are finite <wink>.

Python does store longs in 2's-comp form, but remember that Python longs are
unbounded:  a long less than 0 has a (conceptually) infinite string of
leading 1 bits, just as a long >= 0 has an infinite string of leading 0 bits.
It's easy to show you an infinite string of leading 0 bits:  we just ignore
them.  That infinite string of leading 1 bits isn't so easy to hide, though!

You've been further warped into believing that 32 bits is somehow a "natural"
size for an int.  If that's what you believe, you can force the issue:

>>> hex(~4294965248L & (2L**32 - 1))
'0x7FFL'
>>>

That is, by masking your input with a string of 32 low-order 1-bits, the
infinite string of leading 1 bits goes away, leaving the output you expected.
Or, if you're lucky enough to believe that ints have 101 bits, similarly:

>>> hex(~4294965248L & (2L**101 - 1))
'0x1FFFFFFFFFFFFFFFFF000007FFL'
>>>

So that's the trick:  to represent the infinite by the finite, you either
need a convention, or you need to throw an infinite amount of info away.  The
"-" in '-0xFFFFF801L' is Python's convention for compressing the unbounded
string of sign bits in such a way that no info is lost:

>>> eval(hex(~4294965248L)) == ~4294965248L
1
>>>

next-step:-infinite-memory-ly y'rs  - tim





More information about the Python-list mailing list