mersenneforum.org  

Go Back   mersenneforum.org > Extra Stuff > Programming

Reply
 
Thread Tools
Old 2008-08-22, 13:05   #1
nuggetprime
 
nuggetprime's Avatar
 
Mar 2007
Austria

4568 Posts
Default Noob C question

Hi,
I'm quite a noob to C yet, so I decided to open this thread for noob C questions by me and others.
My first question is: how do I implement a function than checks if an integer is a square number?

Nice day,
nuggetprime
nuggetprime is offline   Reply With Quote
Old 2008-08-22, 13:31   #2
bsquared
 
bsquared's Avatar
 
"Ben"
Feb 2007

3·1,171 Posts
Default

Well, the question is more complicated than that. There are simple ways that are not particularly efficient, but may be fine for your application, or not, depending. This thread goes into some detail about the subtle issues of checking for squaritude quickly on large inputs:
http://www.mersenneforum.org/showthread.php?t=8719

But, for simple purposes on integers less than 2^32, you could just do

Code:
 
int issquare(unsigned int x)
{
   unsigned int root = (unsigned int)sqrt(x);
   if (root * root == x) return 1;
   else return 0;
}
bsquared is offline   Reply With Quote
Old 2008-08-22, 17:43   #3
nuggetprime
 
nuggetprime's Avatar
 
Mar 2007
Austria

12E16 Posts
Default

Thanks,
nugget
nuggetprime is offline   Reply With Quote
Old 2008-08-22, 18:26   #4
ewmayer
2ω=0
 
ewmayer's Avatar
 
Sep 2002
República de California

103×113 Posts
Default

Not quite so fast - the potential problem is that if x is indeed a perfect square, the floating-point sqrt(x) may end up being just a tad less than the true square root due to roundoff error, in which case Bruce's function will yield a false negative.

Methinks there should be a nearest-int in there, say using the "poor man's NINT" like so:

(uint)(sqrt((double)x) + 0.5)

Note: The cast-to-double is also recommended to prevent a potential cast-to-single which could cause the result to overflow a single-precision mantissa. The proper default here (i.e. in the absence of an explicit cast) is cast-to-double, but when dealing with compiled code, it's always best to be safe rather than sorry and cast explicitly. Actually, the round-to-nearest may introduce enough "fudge factor" to make the result correct even if x were cast to single, but I'll let someone else do the error analysis of that scenario, if they are interested.

Last fiddled with by ewmayer on 2008-08-22 at 18:32
ewmayer is offline   Reply With Quote
Old 2008-08-22, 22:29   #5
Batalov
 
Batalov's Avatar
 
"Serge"
Mar 2008
Phi(4,2^7658614+1)/2

22×23×103 Posts
Default

http://alpertron.com.ar/ecm.java has a PowerCheck() routine for checking is a number is a (prime) power. It is very educational to read it. A fantastic and polished piece of work.

If you'd need to port it to C and simplify to check only for squares, there are a few not-so-impassable hurdles. One needs to use e.g. GMP instead of BigInt, so a bit of further documentation reading would be needed. But both of these are highly practical to learn.

(That reminds me of a fantastic and aptly titled 48-pager document that was and maybe still googleable "What Every Computer Scientist Should Know About Floating-Point Arithmetic". Not for this topic, but I cannot find a counter-argument how anyone could have read it and then many years later said - "there was this one time when I wasted so-and-so much time reading that".)

P.S. msieve, I think, has a code that checks for the input number being a power, too. But I didn't have time to find it. Look there. Again, your time will not be wasted.

P.P.S. ((Edit)) using GMP, seems to be already in the library by the way of calling
Code:
mpz_sqrtrem(x,rem,x); /* this means you don't need the root value */
/* catch errors if needed*/
/* then check if rem is zero. Left as an excercise to the reader */
-Serge

Last fiddled with by Batalov on 2008-08-22 at 22:55 Reason: mpz_sqrtrem function
Batalov is offline   Reply With Quote
Old 2008-08-23, 02:59   #6
jasonp
Tribal Bullet
 
jasonp's Avatar
 
Oct 2004

1101110101012 Posts
Default

Quote:
Originally Posted by Batalov View Post
P.S. msieve, I think, has a code that checks for the input number being a power, too. But I didn't have time to find it. Look there. Again, your time will not be wasted.
It's in common/driver.c, in msieve_run_core; basically it makes use of the fact that the input to the library has already had factors below 100k stripped out, so you can extract larger and larger roots until the result is below 100k (or you detect the input is a perfect power by exponentiating each computed root).

GMP has much more advanced algorithms.
jasonp is offline   Reply With Quote
Old 2008-08-23, 11:09   #7
ATH
Einyen
 
ATH's Avatar
 
Dec 2003
Denmark

C5716 Posts
Default

If you use GMP you can check if the function mpz_perfect_square_p(x) is non-zero.

There is also the function mpz_perfect_power_p(x) which returns non-zero if x is any power ab.
ATH is offline   Reply With Quote
Reply

Thread Tools


Similar Threads
Thread Thread Starter Forum Replies Last Post
Noob Question Pickwun Information & Answers 7 2017-11-07 19:17
Noob Question: What to use bozocv Msieve 36 2015-12-31 00:12
Noob Question Unregistered Information & Answers 11 2013-03-23 01:31
Prime 95 Noob Question Unregistered Information & Answers 4 2009-09-12 14:01
Noob question xago666 Information & Answers 3 2008-03-11 01:35

All times are UTC. The time now is 16:59.


Fri Jul 16 16:59:36 UTC 2021 up 49 days, 14:46, 1 user, load averages: 1.65, 1.47, 1.51

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.

This forum has received and complied with 0 (zero) government requests for information.

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation.
A copy of the license is included in the FAQ.