tags:

views:

145

answers:

6

In C (linux) how will I be able to find out if the squareroot of a number is and integer or a floating point. I want to write a program using a function pointer which adds up all the Perfect squares upto the limit sepcified.

+1  A: 
float root = sqrt(number);
int int_root = (int) root;
if ( (root / (float)int_root) == 1.0f ) return "is integer";  

That might work. Optimise it a bit.

or

float root;
if ((root % (int)root) == 0) { return "is integer";)

A simpler solution

int SUM_PERFECT_SQUARES (int limit) {
    int sum = 0;
    for (int i = 0; i < floor(sqrt(limit)); i++) {
        sum += i*i;
    }
    return sum;
}
Raynos
+2  A: 

You may want to look up the paper what every computer scientist should know about floating point arithmetic by David Goldberg and rethink your question.

Dirk Eddelbuettel
+4  A: 

Here you go. Compile it with -lm on Linux.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int checkRoot(double n) {
    long n_sqrt = (long)(sqrt(n)+0.5);
    return n_sqrt*n_sqrt == n;
}

int main() {
    double n = 9.0;
    if(checkRoot(n)) {
        puts("Perfect root.");
    }
    else {
        puts("Not quite.");
    }
    return EXIT_SUCCESS;
}

You should also read this discussion.

vtorhonen
@vtorhonen Thankyou. :) This works but please explain. long n_sqrt = (long)(sqrt(n)+0.5); return n_sqrt*n_sqrt == n;
Pavitar
@Pavitar For example, if `sqrt(9)` gives 2.999999 instead of 3.0, rounding it up would clear that. However, on my processor it seems to calculate it correctly even without the round-up. The return value is simple, as if the squared number to the power of 2 isn't the original number, then it returns 0 (FALSE). If it is, then the return value is 1 (TRUE) and the number is a perfect root.
vtorhonen
The `+0.5` is unnecessary on any platform whose arithmetic conforms to the IEEE-754 standard (which is most platforms, including the questioner's ubuntu/x86)
Stephen Canon
+1  A: 

You can use the Newton-Ralphson method to implement square root for integers yourself. But, for the problem you're talking about, I would recommend calculating the squares of all the integers instead.

/* Returns the greatest integer that's <= to the square root. */
unsigned int isqrt(unsigned int x)
{
    if (x < 4) {
        return 1;
    } else {
        unsigned int try = x / 2;
        while ((x / try) < try) {
            try = (try + (x / try)) / 2;
        }
        return try;
    }
}

int check_perfect_square(unsigned int x)
{
    unsigned int sqrt = isqrt(x);
    return (sqrt * sqrt) == x;
}

And, for my actual suggested solution:

unsigned int sum_perfect_squares(unsigned int limit)
{
    unsigned int sum = 0;
    unsigned int i = 1;
    for (i = 1; i * i < limit; ++i) {
        sum += i * i;
    }
    return sum;
}
Omnifarious
+2  A: 

Not really the answer you are looking for, but I think it is much better to simply sum up the squares of integers which fall into the range than try to use sqrt to determine whether a number is a perfect square (As suggested in some of the comments to the question). This avoids having to use floating point values, which makes it a lot more reliable as a general purpose solution.

#include <stdio.h>

long long sum_squares(int limit){
    int i;
    long long ret=0;
    for (i=1;i*i<=limit;i++){
        ret+=i*i;
    }
    return ret;
}

int main(){
    printf("%lld\n",sum_squares(10));
    return 0;
}
MAK
+1  A: 

Mathematical nit: Assuming your n is an integer, the square root is never a floating point number. It's either an integer (in the case of perfect squares) or an irrational number (which cannot be represented at all except with special symbolic-math libraries).

R..