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". See http://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!). 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. -- Gabriel Genellina -- http://mail.python.org/mailman/listinfo/python-list