Interesting list Validity (True/False)
mensanator at aol.com
mensanator at aol.com
Wed May 16 13:26:33 EDT 2007
On May 16, 4:12 am, "Gabriel Genellina" <gagsl-... at yahoo.com.ar>
wrote:
> En Wed, 16 May 2007 03:16:59 -0300, mensana... at aol.com
> <mensana... at aol.com> escribió:
>
>
>
>
>
> > On May 15, 7:07 pm, "Gabriel Genellina" <gagsl-... at yahoo.com.ar>
> > wrote:
> >> >>>> import gmpy
> >> >>>> a = 2**177149-1
> >> >>>> b = gmpy.mpz(2**177149-1)
> >> >>>> a==b
> >> > True
> >> >>>> print '%d' % (b)
>
> >> > Traceback (most recent call last):
> >> > File "<pyshell#4>", line 1, in <module>
> >> > print '%d' % (b)
> >> > TypeError: int argument required
>
> >> > So although the comparison operator is smart enough to realize
> >> > the equivalency of numeric types and do the type conversion,
> >> > the print statement isn't so smart.
>
> >> This is up to the gmpy designers/writers/maintainers. Anyone writing a
> >> class chooses which features to implement, which ones to omit, how to
> >> implement them, etc. The code may contain bugs, may not be efficient,
> >> may
> >> not behave exactly as the users expect, may not have anticipated all
> >> usage
> >> scenarios, a long etc. In this case, probably the gmpy writers have
> >> chosen
> >> not to allow to convert to int, and they may have good reasons to not do
> >> that (I don't know what platform are you working in, but I feel that
> >> your
> >> b object is somewhat larger than sys.maxint...).
>
> > Then how does this work?
>
> >>>> print '%d' % (long(gmpy.mpz(2**177149-1)))
> > 1454...<53320 digits snipped>...3311
>
> > I honestly don't understand why there's a problem here.
> > If print can handle arbitrary precision longs without
> > a problem, why does it fail on mpzs > sys.maxint?
> > If the gmpy writers are not allowing the conversion,
> > then why do small mpz values work? Something smells
> > inconsistent here.
>
> Python (builtin) "integral numbers" come on two flavors: int and long.
> ints correspond to the C `long` type usually, and have a limited range, at
> least from -2**31 to 2**31-1; most operations have hardware support (or at
> least it's up to the C compiler). Long integers are a totally different
> type, they have unlimited range but are a lot slower, and all operations
> must be done "by hand". Seehttp://docs.python.org/ref/types.html
>
> If you say "%d" % something, Python first tries to see if `something` is a
> long integer -not to *convert* it to a long integer, just to see if the
> object *is* a long integer. If it's a long, it's formatted accordingly.
> If not, Python sees if `something` is a plain integer. If not, it sees if
> it's a number (in this context, that means that the structure describing
> its type contains a non-NULL tp_as_number member) and tries to *convert*
> it to an integer. Notice that if the object whas not originally a long
> integer, no attempt is made to convert it to a long using the nb_long
> member - just a plain integer conversion is attempted.
> It's at this stage that a large mpz object may fail - when its value can't
> fit in a plain integer, it raises an OverflowError and the "%d" formatting
> fails.
> If you force a conversion to long integer, using long(mpz(...)) as above,
> the % operator sees a long integer from start and it can be formatted
> without problems.
>
> I don't know if this asymmetric behavior is a design decision, a historic
> relic, a change in protocol (is nb_int allowed now to return a
> PyLongObject, but not before?), a "nobody cares" issue, or just a bug.
> Perhaps someone else can give an opinion - and certainly I may be wrong, I
> had never looked at the PyString_Format function internal details before
> (thanks for providing an excuse!).
Ah, thanks for the info, I know nothing about Python internals.
That implies that although this works:
>>> print '%d' %(1234567890.0)
1234567890
this does not:
>>> print '%d' %(12345678901234567890.0)
Traceback (most recent call last):
File "<pyshell#1>", line 1, in <module>
print '%d' %(12345678901234567890.0)
TypeError: int argument required
So we can work around it by doing the long conversion
ourselves since print only knows how to invoke int conversion.
>>> print '%d' %(long(12345678901234567890.0))
12345678901234567168
which demonstartes the problem is not with gmpy.
>
> As a workaround you can always write "%d" % long(mpznumber) when you want
> to print them (or perhaps "%s" % mpznumber, which might be faster).
>
> > How is it that
>
> >>>> print '%d' % (1.0)
> > 1
>
> > doesn't make a type mismatch? Obviously, the float
> > got changed to an int and this had nothing to do with
> > gmpy. Is it the print process responsible for doing
> > the conversion? Maybe I should say invoking the
> > conversion? Maybe the gmpy call tries to literally
> > convert to an integer rather than sneakily substitute
> > a long?
>
> Same as above: is the argument a long integer? no. is it a number? yes.
> Convert to int. No errors? Apply format.
Thanks again, as long as I know why the behaviour is strange,
I know how to work around it
>
> --
> Gabriel Genellina
More information about the Python-list
mailing list