1

I have to find 4 digits number of the form XXYY that are perfect squares of any integer. I have written this code, but it gives the square root of all numbers when I have to filter only perfect integer numbers.

I want to show sqrt(z) only when it is an integer.

#include<math.h>
#include<iostream.h>
#include<conio.h>
void main()
{
 int x,y=4,z;
 clrscr();
 for(x=1;x<=9;x++)
 {
  z=11*(100*x+y);
  cout<<"\n"<<sqrt(z);

 }
 getch();
}
moinudin
  • 134,091
  • 45
  • 190
  • 216
Atul
  • 1,157
  • 2
  • 16
  • 28
  • To clarify, what you're asking is "How can I test when z is a square number? e.g. how can I test if sqrt(z) returns an integer result?" – Rup Jan 09 '11 at 13:17
  • Can you post an example?the question is not clear – programmer Jan 09 '11 at 15:14
  • For the unwary: A perfect square of four digits will have its last too digits be 44, so the `XXYY` pattern is in fact reduced to `XX44`. Thanks to Steve Jessop to have pointing it out to me :p – Matthieu M. Jan 09 '11 at 16:03
  • 1
    @Matthieu: `00` is also possible (1600, 2500, etc.). – dan04 Jan 10 '11 at 01:12
  • @dan04: sorry, I didn't expressed myself precisely enough. A square of the form XXYY is necessarily of the form XX44. There are other squares of 4 digits, but their first two digits are different from one another. – Matthieu M. Jan 10 '11 at 07:37
  • True, unless you count `0000`. – dan04 Jan 10 '11 at 08:11

9 Answers9

3

I'd probably check it like this, because my policy is to be paranoid about the accuracy of math functions:

double root = sqrt(z);
int introot = floor(root + 0.5); // round to nearby integer
if ((introot * introot) == z) {  // integer arithmetic, so precise
    cout << introot << " == sqrt(" << z << ")\n";
}

double can exactly represent all the integers we care about (for that matter, on most implementations it can exactly represent all the values of int). It also has enough precision to distinguish between sqrt(x) and sqrt(x+1) for all the integers we care about. sqrt(10000) - sqrt(9999) is 0.005, so we only need 5 decimal places of accuracy to avoid false positives, because a non-integer square root can't be any closer than that to an integer. A good sqrt implementation therefore can be accurate enough that (int)root == root on its own would do the job.

However, the standard doesn't specify the accuracy of sqrt and other math functions. In C99 this is explicitly stated in 5.2.4.2.2/5: I'm not sure whether C89 or C++ make it explicit. So I'm reluctant to rule out that the result could be out by a ulp or so. int(root) == root would give a false negative if sqrt(7744) came out as 87.9999999999999-ish

Also, there are much larger numbers where sqrt can't be exact (around the limit of what double can represent exactly). So I think it's easier to write the extra two lines of code than to write the comment explaining why I think math functions will be exact in the case I care about :-)

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
2
#include <iostream>
int main(int argc, char** argv) {
    for (int i = 32; i < 100; ++i) { 
        // anything less than 32 or greater than 100 
        // doesn't result in a 4-digit number
        int s = i*i;
        if (s/100%11==0 && s%100%11==0) {
            std::cout << i << '\t' << s << std::endl;
        }
    }
}

http://ideone.com/1Bn77

etarion
  • 16,935
  • 4
  • 43
  • 66
2

There is absolutely no need to involve floating point math in this task at all. Here's an efficient piece of code that will do this job for you.

Since your number has to be a perfect square, it's quicker to only check perfect squares up front rather than all four digit numbers, filtering out non-squares (as you would do in the first-cut naive solution).

It's also probably safer to do it with integers rather than floating point values since you don't have to worry about all those inaccuracy issues when doing square root calculations.

#include <stdio.h>
int main (void) {
    int d1, d2, d3, d4, sq, i = 32;
    while ((sq = i * i) <= 9999) {
        d1 = sq / 1000;
        d2 = (sq % 1000) / 100;
        d3 = (sq % 100) / 10;
        d4 = (sq % 10);
        if ((d1 == d2) && (d3 == d4))
            printf ("   %d\n", i * i);
        i++;
    }
    return 0;
}

It relies on the fact that the first four-digit perfect square is 32 * 32 or 1024 (312 is 961). So it checks 322, 332, 342, and so on until you exceed the four-digit limit (that one being 1002 for a total of 69 possibilities whereas the naive solution would check about 9000 possibilities).

Then, for every possibility, it checks the digits for your final XXYY requirement, giving you the single answer:

7744
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • "it's quicker to only check perfect squares up front rather than all four digit numbers" - he's not checking all 4-digit numbers, though, he's only checking 9 of them. Not that speed is really a concern for such a small task as this, but I think you're comparing your code to a straw man. – Steve Jessop Jan 09 '11 at 14:01
  • @Steve: the question and the code disagrees though, as the question does state he wants them all. However I disagree that a brute force solution would be to test all four-digits number: we have a pattern, so we only have to check 90 of them (1 <= x <= 9, 0 <= y <= 9, xxyy), unless we also want x to be equal to 0, in which case there would be exactly 100 of them. @paxdiablo: could you state that you check from 32 to 99 (included) so that it is clear the loop is only executed 68 times ? – Matthieu M. Jan 09 '11 at 15:52
  • @Matthieu: the original poster has used mathematics. If the last two decimal digits of a square number are equal, then they necessarily are `44`. So the question and code do agree. Perhaps not obviously so: personally I think that trick deserves a comment :-) – Steve Jessop Jan 09 '11 at 15:56
  • @Steve: Ah, that would have been easier if it had been stated :p So it's 9 square root computations against 68 square computations. Our poster may already have the fastest answer :) – Matthieu M. Jan 09 '11 at 15:59
  • @Matthieu: (or `00`, but we can rule that out in this case. `aa00` isn't square for any digit `a`, because `aa` isn't square for any digit `a`). To be honest, with this much mathematics already applied it's barely worth writing any code at all, just check the last 9 cases on a calculator, and write the program as `int main() { std::cout << 7744 << "\n"; }` ;-) – Steve Jessop Jan 09 '11 at 16:01
  • @Steve (for the first comment) - Sorry, I wasn't saying my answer was more efficient than the OP's, just that it's more efficient than the first-thought brute-force solution. As to the search space for solutions, my code uses the knowledge that 32 is the minimal square root for a four digit number, something reasonably easy to deduce. The knowledge that all such numbers would end in 44 is somewhat less intuitive and, as you rightly state later, it's a short step from there to the knowledge that the answer is 7744 and just use your one-line `cout` solution :-) – paxdiablo Jan 10 '11 at 01:03
2

We can notice that

  • 1 + 3 = 2^2
  • 1 + 3 + 5 = 3^2,
  • 1 + 3 + 5 + 7 = 4^2,

i.e. sum(1 + 3 + ... (2N + 1)) for any N is a square. (it is pretty easy to prove)

Now we can generate all squares in [0000, 9999] and check each square if it is XXYY.

Michael
  • 41,026
  • 70
  • 193
  • 341
1

While I smell a homework question, here is a bit of guidance. The problem with this solution is you are taking the square root, which introduces floating point arithmetic and the problems that causes in precise mathematics. You can get close by doing something like:

double epsilon = 0.00001;
if ((z % 1.0) < epsilon || (z % 1.0) + epsilon > 1) {
    // it's probably an integer
}

It might be worth your while to rewrite this algorithm to just check if the number conforms to that format by testing the squares of ever increasing numbers. The highest number you'd have to test is short of the square root of the highest perfect square you're looking for. i.e. sqrt(9988) = 99.93... so you'd only have to test at most 100 numbers anyway. The lowest number you might test is 1122 I think, so you can actually start counting from 34.

There are even better solutions that involve factoring (and the use of the modulo operator) but I think those are enough hints for now. ;-)

SapphireSun
  • 9,170
  • 11
  • 46
  • 59
  • I should note that it's been a while since I used c++, so for all I know the sqrt operator might be (probably is) perfect for perfect squares. – SapphireSun Jan 09 '11 at 13:21
  • 1
    any *reasonable* implementation of `sqrt` will return an integer for a 4-digit perfect square. I don't think the standard actually specifies accuracy, though, so it's not a bad idea to have a tolerance which is (a) larger than the most inaccurate you think a sqrt implementation will ever be; and also (b) not so large as to give false positives, which I think 0.00001 satisfies. – Steve Jessop Jan 09 '11 at 13:52
  • @marcog: Sorry, you can do that in python and I'm a bit rusty in c++. My bad. – SapphireSun Jan 09 '11 at 21:14
0

To check if sqrt(x) is an integer, compare it to its floored value:

sqrt(x) == (int) sqrt(x)

However, this is actually a bad way to compare floating point values due to precision issues. You should always factor in a small error component:

abs(sqrt(x) - ((int) sqrt(x))) < 0.0000001

Even if you make this correction though, your program will still be outputting the sqrt(z) when it sounds like what you want to do is output z. You should also loop through all y values, instead of just considering y=4 (note that y an also be 0, unlike x).

moinudin
  • 134,091
  • 45
  • 190
  • 216
0

The way you are generating numbers is incorrect indeed correct (my bad) so all you need is right way to find square. : )

loop x: 1 to 9
  if(check_for_perfect_square(x*1100 + 44))
         print: x*1100 + 44

see here for how to find appropriate square Perfect square and perfect cube

Community
  • 1
  • 1
Nishant
  • 54,584
  • 13
  • 112
  • 127
  • Actually it is correct, he's using the cunning fact that if the last two decimal digits of a square number are equal, then they must be `44`. – Steve Jessop Jan 09 '11 at 13:26
0

I want to show the sqrt(z) only when it is integer.

double result = sqrt( 25); // Took 25 as an example. Run this in a loop varying sqrt
                           // parameter
int checkResult = result;
if ( checkResult == result )
    std::cout << "perfect Square" ;
else
    std::cout << "not perfect square" ;
Mahesh
  • 34,573
  • 20
  • 89
  • 115
0

You don't need to take square roots. Notice that you can easily generate all integer squares, and all numbers XXYY, in increasing order. So you just have to make a single pass through each sequence, looking for matches:

 int n = 0 ;
 int X = 1, Y = 0 ; // Set X=0 here to alow the solution 0000
 while (X < 10) {
   int nSquared = n * n ;
   int XXYY = 1100 * X + 11 * Y ;

   // Output them if they are equal
   if (nSquared == XXYY) cout << XXYY << endl ;

   // Increment the smaller of the two
   if (nSquared <= XXYY) n++ ;
   else if (Y < 9) Y++ ;
   else { Y = 0 ; X++ ; }
   }
TonyK
  • 16,761
  • 4
  • 37
  • 72