Best way to test whether a number is an integer

20 views
Skip to first unread message

rpmu...@gmail.com

unread,
Feb 7, 2008, 10:54:20 AM2/7/08
to sage-newbie
I'm using sage as my secret weapon in solving some of the problems on
Project Euler. One of the things I need to do is figure out whether a
number is an integer or not.

If I have a rational number, I can do something like:

sage: (3/4).is_integral()
False

But this doesn't work if I have square roots:

sage: sqrt(9).is_integral()
---------------------------------------------------------------------------
<type 'exceptions.AttributeError'> Traceback (most recent call
last)

/Users/rmuller/Python/Pistol/ProjectEuler/<ipython console> in
<module>()

<type 'exceptions.AttributeError'>: 'SymbolicComposition' object has
no attribute 'is_integral'

Is there some way to do this intelligently? The python routine I use:

def isint(n): return int(n) == n

works until the python floats start getting big an inaccurate.

David Joyner

unread,
Feb 7, 2008, 11:12:24 AM2/7/08
to sage-...@googlegroups.com
This doesn't answer your general question, but as a workaround in the
example you cited, you can use is_square:

sage: a = 9
sage: a.is_square()
True

rpmu...@gmail.com

unread,
Feb 7, 2008, 11:20:48 AM2/7/08
to sage-newbie
Thanks, that does indeed get me past my block. I'd be glad to hear
other solutions, as well, since it will help me learn more about sage.

On Feb 7, 9:12 am, "David Joyner" <wdjoy...@gmail.com> wrote:
> This doesn't answer your general question, but as a workaround in the
> example you cited, you can use is_square:
>
> sage: a = 9
> sage: a.is_square()
> True
>

William Stein

unread,
Feb 7, 2008, 1:49:50 PM2/7/08
to sage-...@googlegroups.com
On Feb 7, 2008 8:20 AM, rpmu...@gmail.com <rpmu...@gmail.com> wrote:
>
> Thanks, that does indeed get me past my block. I'd be glad to hear
> other solutions, as well, since it will help me learn more about sage.
>
> On Feb 7, 9:12 am, "David Joyner" <wdjoy...@gmail.com> wrote:
> > This doesn't answer your general question, but as a workaround in the
> > example you cited, you can use is_square:
> >
> > sage: a = 9
> > sage: a.is_square()
> > True

Coerce to Integer and use try/except:

sage: try:
Integer(sqrt(7))
except TypeError:
print "sqrt(7) is not an integer."
....:
sqrt(7) is not an integer.

sage: try:
Integer(sqrt(9))
except TypeError:
print "sqrt(9) is not an integer."
....:
3

rpmu...@gmail.com

unread,
Feb 11, 2008, 1:38:27 PM2/11/08
to sage-newbie
Thanks for all of the suggestions. I have a follow-on question:

I can see by looking at the source code to "is_square??" that the Sage
function just wraps Pari's is_square function. Can anyone tell me a
simple way to figure out whether a number is square, other than:

>>> squares = Set(i*i for i in range(1,very_big_number))
>>> def is_square(n): return n in squares

which gets memory intensive for really large values of
very_big_number.

On Feb 7, 11:49 am, "William Stein" <wst...@gmail.com> wrote:

rpmu...@gmail.com

unread,
Feb 11, 2008, 2:50:30 PM2/11/08
to sage-newbie
I was curious enough about this to answer my own question. I coded up
the following for the integer square root:
def isqrt(n):
xn = 1
xn1 = (xn + n/xn)/2
while abs(xn1 - xn) > 1:
xn = xn1
xn1 = (xn + n/xn)/2
while xn1*xn1 > n:
xn1 -= 1
return xn1
which I got from:
http://www.codecodex.com/wiki/index.php?title=Calculate_an_integer_square_root

I can then use:

def is_square(n): return isqrt(n)**2 == n

which works quite nicely.

William Stein

unread,
Feb 12, 2008, 12:49:41 AM2/12/08
to sage-...@googlegroups.com
On Feb 11, 2008 10:38 AM, rpmu...@gmail.com <rpmu...@gmail.com> wrote:
>
> Thanks for all of the suggestions. I have a follow-on question:
>
> I can see by looking at the source code to "is_square??" that the Sage
> function just wraps Pari's is_square function. Can anyone tell me a
> simple way to figure out whether a number is square, other than:
>
> >>> squares = Set(i*i for i in range(1,very_big_number))
> >>> def is_square(n): return n in squares
>
> which gets memory intensive for really large values of
> very_big_number.

Use the is_square *method* of integers:

sage: n = 100
sage: n.is_square()
True
sage: n = 100919080981232
sage: n.is_square()
False

The above is implemented by a single call into
the GMP library:

sage: n.is_square??
...
def is_square(self):
r"""
Returns \code{True} if self is a perfect square

EXAMPLES:
sage: Integer(4).is_square()
True
sage: Integer(41).is_square()
False
"""
return mpz_perfect_square_p(self.value)


This is going to be *vastly* faster than anything
you are likely to write:

sage: n = 100919080981232
sage: time for _ in xrange(10^6): a = n.is_square()
CPU times: user 0.29 s, sys: 0.00 s, total: 0.29 s
sage: time v = [n.is_square() for n in [1..10^6]]
CPU times: user 0.53 s, sys: 0.14 s, total: 0.68 s
Wall time: 2.50
sage: len(v)
1000000

Reply all
Reply to author
Forward
0 new messages