# Encontrar todos los cuadrados perfectos de la forma XXYY

Frecuentes

Visto tiempos 5,216

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.

quiero mostrar `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();
}
```

## 9 Respuestas

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)`

y `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 :-)

Respondido el 09 de enero de 11 a las 19:01

+1 the obvious square root check is to check the produced square - Matthieu M.

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;
}
}
}
```

Respondido el 09 de enero de 11 a las 16:01

2

We can notice that

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

es decir, `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.

Respondido el 09 de enero de 11 a las 22:01

2

Hay absolutamente *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`

(31^{2} is 961). So it checks 32^{2}, 33^{2}, 34^{2}, and so on until you exceed the four-digit limit (that one being 100^{2} 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
```

respondido 13 nov., 15:10

"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

@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.

@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

@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.

@Matthieu: (or `00`

, but we can rule that out in this case. `aa00`

isn't square for any digit `a`

, porque `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

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. ;-)

Respondido el 09 de enero de 11 a las 16:01

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. - ZafiroSol

cualquier *mejor* aplicación de `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

@marcog: Sorry, you can do that in python and I'm a bit rusty in c++. My bad. - ZafiroSol

0

Para verificar si `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`

(tenga en cuenta que `y`

an also be 0, unlike `x`

).

Respondido el 09 de enero de 11 a las 16:01

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" ;
```

Respondido el 09 de enero de 11 a las 16:01

0

The way you are generating numbers is ~~incorrecto~~ *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

contestado el 23 de mayo de 17 a las 15:05

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

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++ ; }
}
```

Respondido el 10 de enero de 11 a las 00:01

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas c++ algorithm or haz tu propia pregunta.

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

Can you post an example?the question is not clear - programmer

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.@ Matthieu:

`00`

is also possible (1600, 2500, etc.). - dan04@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.