13

How can you test whether the square root of a number will be rational or not?

Is this even possible?

I need this because I need to work out whether to display a number as a surd or not in a maths app I'm developing at the moment.

Alex Coplan
  • 13,211
  • 19
  • 77
  • 138
  • This may be more adpt for math.stackexchange.com. They would give you the slgorithm which you can then implement here. – Dheer Nov 16 '11 at 11:11
  • 2
    @Dheer for proof the fact that he's actually searching for perfect squares, yes; but for a *computational* approach to testing that, this is the right place. After all, for a mathematician the answer to 'is `n` a perfect square?' is simply 'iff `sqrt(n)` is an integer', which isn't much help programatically. – AakashM Nov 16 '11 at 11:16
  • what do you mean by number? integer, rational? floating point? – jk. Nov 16 '11 at 11:20
  • float/double (in terms of datatype) but it's likely to be an integer (not in terms of the datatype) – Alex Coplan Nov 16 '11 at 11:22
  • @AakashM: [I believe you have made some wrong assumptions about square roots.](http://www.wolframalpha.com/input/?i=sqrt%5B0.0625%5D) – sarnold Nov 16 '11 at 11:25
  • @sarnold indeed, I hadn't even considered non-integers. Pedantically I note that my using an `n` in my comment *obviously* means I'm talking about an integer :) – AakashM Nov 16 '11 at 11:33

5 Answers5

6

For integer inputs, only the square roots of the square numbers are rationals. So your problem boils down to find if your number is a square number. Compare the question: What's a good algorithm to determine if an input is a perfect square?.

If you have rational numbers as inputs (that is, a number given as the ratio between two integer numbers), check that both divisor and dividend are perfect squares.

For floating-point values, there is probably no solution because you can't check if a number is rational with the truncated decimal representation.

Community
  • 1
  • 1
thiton
  • 35,651
  • 4
  • 70
  • 100
  • 3
    -1: You've forgotten that square roots can be taken on _any_ number, not just integers. Quoth Wikipedia: [The square root of x is rational if and only if x is a rational number that can be represented as a ratio of two perfect squares.](http://en.wikipedia.org/wiki/Square_root). – sarnold Nov 16 '11 at 11:22
  • All finite floating point numbers are rational. There's no checking to do. – Stephen Canon Nov 16 '11 at 13:21
  • @StephenCanon: But each represents an infinite number of rational and irrational numbers that all got the same finite FP representation. – thiton Nov 16 '11 at 13:24
  • @thiton: No, each represents precisely one rational number. Other numbers are rounded to the closest representable value. Would you say that the integer 3 "represents" 3.2, because if I write `int x = 3.2` I actually get `x == 3`? – Stephen Canon Nov 16 '11 at 13:53
3

From wikipedia: The square root of x is rational if and only if x is a rational number that can be represented as a ratio of two perfect squares.

So you need to find a rational approxmiation for your input number. So far the only algorithm I've nailed down that does this task is written in Saturn Assembler for the HP48 series of calculators.

sarnold
  • 102,305
  • 22
  • 181
  • 238
2

After reading comments and the answers to another question I have since asked, I realised that the problem came from a floating point inaccuracy which meant that some values (eg 0.01) would fail the logical test at the end of the program. I have amended it to use NSDecimalNumber variables instead.

double num, originalnum, multiplier;
int a;

NSLog(@"Enter a number");
scanf("%lf", &num);
//keep a copy of the original number
originalnum = num;

//increases the number until it is an integer, and stores the amount of times it does it in a
for (a=1; fmod(num, 1) != 0 ; a++) {
    num *= 10;
}

a--;
//when square-rooted the decimal points have to be added back in
multiplier = pow(10, (a/2));
if (fmod(originalnum, 1) != 0) {
    multiplier = 10;
}

NSDecimalNumber *temp = [NSDecimalNumber decimalNumberWithDecimal:[[NSNumber numberWithDouble:sqrt(num)/multiplier] decimalValue]];
NSDecimalNumber *result = [temp decimalNumberByMultiplyingBy:temp];
NSDecimalNumber *originum = [NSDecimalNumber decimalNumberWithDecimal:[[NSNumber numberWithDouble:originalnum] decimalValue]];

if ((fmod(sqrt(num), 1) == 0) && ([result isEqualToNumber:originum])) {
    NSLog(@"The square root of %g is %@", originalnum, temp);
}
else {
    NSLog(@"The square root of this number is irrational");
}
Community
  • 1
  • 1
  • -1 testing this algorithm with 1f/3f squared, with 0.1f squared, with 0.101f squared results in "The square root of this number is irrational". You need to represent the numerator and devisor exactly as integers and test whether they are exact squares. – Pete Kirkham Nov 22 '11 at 19:19
1

If you're dealing with integers, note that a positive integer has a rational square root if and only if it has an integer square root, that is, if it is a perfect square. For information on testing for that, please see this amazing StackOverflow question.

Community
  • 1
  • 1
AakashM
  • 62,551
  • 17
  • 151
  • 186
0

On https://math.stackexchange.com/ there is the question What rational numbers have rational square roots? that yielded an answer from Jakube that states that for "...rational numbers, an answer is to determine if the numerator and denominator are integers raised to the power of 2."

Good ways to work out whether natural numbers are perfect squares depends on the natural numbers the function supports (and the computer programming language being used) and the memory available etc. Here are a set of useful links:

I developed and tested a solution in Java that works well enough for me with a set of natural numbers. The gist of this is given below. This code depends on BigMath and is implemented in agdt-java-math albeit in a couple of different classes:

    /**
     * @param x The number to return the square root of (if the result is
     * rational).
     * @return The square root of x if that square root is rational and
     * {@code null} otherwise.
     */
    public static BigRational getSqrtRational(BigRational x) {
        BigInteger[] numden = getNumeratorAndDenominator(x);
        BigInteger nums = getPerfectSquareRoot(numden[0]);
        if (nums != null) {
            BigInteger dens = getPerfectSquareRoot(numden[1]);
            if (dens != null) {
                return BigRational.valueOf(nums).divide(BigRational.valueOf(dens));
            }
        }
        return null;
    }

    /**
     * @param x The value for which the numerator and denominator are returned.
     * @return The numerator and denominator of {@code x}
     */
    public static BigInteger[] getNumeratorAndDenominator(BigRational x) {
        BigInteger[] r = new BigInteger[2];
        r[0] = x.getNumeratorBigInteger();
        r[1] = x.getDenominatorBigInteger();
        if (Math_BigInteger.isDivisibleBy(r[0], r[1])) {
            r[0] = r[0].divide(r[1]);
            r[1] = BigInteger.ONE;
        }
        return r;
    }

    /**
     * @param x The number to return the square root of if that is an integer.
     * @return The square root of {@code x} if it is an integer and {@code null}
     * otherwise.
     */
    public static BigInteger getPerfectSquareRoot(BigInteger x) {
        if (x.compareTo(BigInteger.ZERO) != 1) {
            return null;
        }
        BigInteger xs = x.sqrt();
        if (x.compareTo(xs.multiply(xs)) == 0) {
            return xs;
        }
        return null;
    }

Also as square of any rational is rational, no rational is the square root of an irrational. This is clear to me having read Yves answer to: Prove that the square root of any irrational number is irrational. So, dealing with the case of rational numbers is sufficient to answer this question for all real numbers.