Re: Interesting list Validity (True/False)



On May 16, 4:12 am, "Gabriel Genellina" <gagsl-...@xxxxxxxxxxxx>
wrote:
En Wed, 16 May 2007 03:16:59 -0300, mensana...@xxxxxxx
<mensana...@xxxxxxx> escribió:





On May 15, 7:07 pm, "Gabriel Genellina" <gagsl-...@xxxxxxxxxxxx>
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

.



Relevant Pages

  • Re: Interesting list Validity (True/False)
    ... This is up to the gmpy designers/writers/maintainers. ... not to allow to convert to int, and they may have good reasons to not do ... If the gmpy writers are not allowing the conversion, ... 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. ...
    (comp.lang.python)
  • Re: Problem with linker
    ... but to have actually written a default constructor. ... such as overloading on int and pointer types. ... conversion of 0 to CString requires a user-defined conversion, ... acceleration operator *(distance d, time_squared t2); ...
    (microsoft.public.vc.mfc)
  • Re: if(a);
    ... The type of the octal signed int literal 0 will be compared to the ... 'a' has type unsigned int, in which case 0 is converted to ... is still 0 after undergoing conversion, ...
    (comp.lang.c)
  • Re: [PATCH 1/2] Add function to convert between calendar time and broken-down time for universal
    ... convert time between calendar time and broken-down time. ... replace `int' with `unsigned int', ... needed of your email client is performing tab-to-space conversion. ... * Library General Public License for more details. ...
    (Linux-Kernel)
  • Re: Re: [PATCH 1/2] Add function to convert between calendar time and broken-down time for unive
    ... A example is my patch for fs/fat/misc.c. ... replace `int' with `unsigned int', ... needed of your email client is performing tab-to-space conversion. ... * Library General Public License for more details. ...
    (Linux-Kernel)