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

Reply via email to