On Sat, Jun 02, 2001 at 08:15:21PM -0600, Eric W. Biederman wrote:
> Bob Drzyzgula <[EMAIL PROTECTED]> writes:
>
> > I'll research this a bit more if you like... perhaps
> > there's a patch or a straightforward workaround (other
> > than the obvious "upgrade to Python 2.x").
> >
> > But, I suppose, you can at least take comfort in the fact
> > that it's not a user headspace error...
>
> Given that I haven't really learned python yet, I was suspecting
> lack of knowledge. We need reliable handling of unsigned 32 bit
> numbers so upgrade to python 2.0 is likely best, unless there
> is a good workaround. If the solution is upgraed to 2.0 we need
> a way to check to make certain you are running python 2.0
Eric,
Short answer:
print "%s" % string.lower(hex(string.atol("0xfffff000", 0))[:-1])
This gives the same -- and desired -- result in both
1.5.2 and 2.0. The [:-1] thing is because hex() will
put an "L" at the end of the number.
Long answer:
Looking into it some more, this appears to be an
artifact of the facts that (a) Python does not directly
support 32-bit unsigned integers as such, and (b) the %x
conversion is intended only to support integer arguments,
not long integers -- my guess is that they had been relying
on the regular sprintf conversions from the underlying
C libraries for this.
In Python, an "integer" is a normal four or eight byte
(depending on the underlying hardware) integer type --
what would normally be called a "long int" in C. Python's
"long integer", however, is by design unbounded, in reality
bounded by system memory. Thus, Python should be able to
support arithmetic among million-digit integers as long
as your system has the memory for it. (My apologies if
you already knew this...)
It appears that the %x conversion was originally coded to
properly handle only regular integers, not long integers.
I suspect that what is happening in your code fragment
is that:
* The "atol" call (always) returns a long (unbounded)
integer.
* The number 0xfffff000 is in the range that, if treated
as a signed, 32-bit int would be negative, but atol
treats it as a positive value; after all, if you
had wanted a negative number, you would have coded
"-0xfffff000", n'est pas? (Try it -- it works :-).
* (guessing) When you do the "0x%x" % bignum conversion,
Python is probably first recasting the numeric argument
to a normal, four-byte int because the %x format
requires it. Since 4,294,963,200 is outside of the
range for integers, you get the overflow.
* (guessing) This was such a hassle for people (you can
find discussion threads on this going back years, the
earliest I noticed was from 1996 or so...) that they finally
changed %x to properly handle long ints in Python 2.0.
In comp.lang.python threads on this topic, the answer almost
always has been to use the hex() function; hex() is
guaranteed to work correctly for long integers, whereas
%x is not. The main complication is that hex() will put
the "0x" and "L" decorations on the number, so you have
to substring the result if you don't want them -- just the
opposite of the convention for %x.
--Bob