Re: Interesting list Validity (True/False)
- From: "mensanator@xxxxxxx" <mensanator@xxxxxxx>
- Date: 16 May 2007 10:26:33 -0700
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:
Trueimport gmpy
a = 2**177149-1
b = gmpy.mpz(2**177149-1)
a==b
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?
1454...<53320 digits snipped>...3311print '%d' % (long(gmpy.mpz(2**177149-1)))
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:
1234567890print '%d' %(1234567890.0)
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.
12345678901234567168print '%d' %(long(12345678901234567890.0))
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
1print '%d' % (1.0)
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
.
- References:
- Re: Interesting list Validity (True/False)
- From: Carsten Haese
- Re: Interesting list Validity (True/False)
- From: mensanator@xxxxxxx
- Re: Interesting list Validity (True/False)
- From: Carsten Haese
- Re: Interesting list Validity (True/False)
- From: mensanator@xxxxxxx
- Re: Interesting list Validity (True/False)
- From: Steven D'Aprano
- Re: Interesting list Validity (True/False)
- From: mensanator@xxxxxxx
- Re: Interesting list Validity (True/False)
- From: Steven D'Aprano
- Re: Interesting list Validity (True/False)
- From: mensanator@xxxxxxx
- Re: Interesting list Validity (True/False)
- From: Carsten Haese
- Re: Interesting list Validity (True/False)
- From: mensanator@xxxxxxx
- Re: Interesting list Validity (True/False)
- From: Gabriel Genellina
- Re: Interesting list Validity (True/False)
- From: mensanator@xxxxxxx
- Re: Interesting list Validity (True/False)
- From: Gabriel Genellina
- Re: Interesting list Validity (True/False)
- From: mensanator@xxxxxxx
- Re: Interesting list Validity (True/False)
- From: Gabriel Genellina
- Re: Interesting list Validity (True/False)
- Prev by Date: cPickle.dumps differs from Pickle.dumps; looks like a bug.
- Next by Date: Re: A bug in cPickle?
- Previous by thread: Re: Interesting list Validity (True/False)
- Next by thread: Re: Interesting list Validity (True/False)
- Index(es):
Relevant Pages
|