On May 16, 4:12 am, "Gabriel Genellina" <[EMAIL PROTECTED]> wrote: > En Wed, 16 May 2007 03:16:59 -0300, [EMAIL PROTECTED] > <[EMAIL PROTECTED]> escribió: > > > > > > > On May 15, 7:07 pm, "Gabriel Genellina" <[EMAIL PROTECTED]> > > 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 -- http://mail.python.org/mailman/listinfo/python-list