Encontrar todos los cuadrados perfectos de la forma XXYY

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.

void main()
 int x,y=4,z;


preguntado el 09 de enero de 11 a las 13:01

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?" -

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

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

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

9 Respuestas

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

#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

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

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


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

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

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

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" ;
    std::cout << "not perfect square" ;

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

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

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 or haz tu propia pregunta.