How to identify and print perfect squares with Javascript?

Asked

Viewed 2,688 times

1

I need a Javascript function that prints an HTML counter from 1 to 100. When the number is a perfect square, should print the text "perfect square" after the number.

Example:

1 
2
3
4 QUADRADO PERFEITO
5
6
7
8
9 QUADRADO PERFEITO
10
11
12
13
14
15
16 QUADRADO PERFEITO ...
  • 9

    As the question gives no further details, it follows a possibility: function QuadradoPerfeito() { document.write( "1 2 3 4 QUADRADO PERFEITO 5 6 7 8 9 QUADRADO PERFEITO 10 11 12 13 14 15 16 QUADRADO PERFEITO 17 18 19 20 21 22 23 24 25 QUADRADO PERFEITO 26 27 28 29 30 31 32 33 34 35 36 QUADRADO PERFEITO 37 38 39 40 41 42 43 44 45 46 47 48 49 QUADRADO PERFEITO 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 QUADRADO PERFEITO 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 QUADRADO PERFEITO 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 QUADRADO PERFEITO" ) } :P

  • I don’t understand what you mean by "perfect square":P

  • 2

    @Ricardo http://pt.wikipedia.org/wiki/Quadrado_perfeito

3 answers

17

Note that your example is incorrect as 1 is perfect square as well.

Follows a possibility, without much optimization:

function QuadradoPerfeito( n ) {
  var i;
  var out = '';
  var root;

  for ( i = 1; i <= n; i++ ) {
    root = Math.sqrt( i );
    if ( root == Math.floor( root ) ) {
      out += i + ' QUADRADO PERFEITO<br>';
    } else {
      out += i + '<br>';
    }
  }
  return out;
}

document.body.innerHTML = QuadradoPerfeito( 100 );


Summary explanation:

When iterating the numbers, we see if the square root of the number ( Math.sqrt ) is an integer number. If it is, the number is a perfect square. To check if it is an integer, simply take out the decimals using the Math.floor and see if the number has changed.


Optimizing the function with conditional operator and the operator of rest:

function QuadradoPerfeito( n ) {
  var i;
  var out = '';
  var root;

  for ( i = 1; i <= n; i++ )
    out += i + ( Math.sqrt( i ) % 1 === 0 ? ' QUADRADO PERFEITO' : '' ) + '<br>';

  return out;
}

document.body.innerHTML = QuadradoPerfeito( 100 );


Summary explanation:

The conditional operator replaces the if (more details, just click on the link) while doing the whole test.

The split rest operator (called erroneously module in some literature, is not the same thing) serves to eliminate the need for Math.floor. If we divide the root of the number by one, take the rest (which is what % does) and that rest is zero, it means that i a Perfect Square.

  • Thank you very much. I’m a beginner but I learned a lot from your information. I just changed the print. window.onload = QuadradoPerfeito; document.write (QuadradoPerfeito( 100 ));

  • Nothing like a === to help optimize large loops :) +1

  • @Guilhermenascimento in lack of practice in JS, I got that thing in my head to make sure I was not going to compare int with float, etc... I was wondering if it was == just :P

  • I was actually praising your second code. It seems to me to be correct, but in the matter of Math. I also have no practice, but still congratulations :)

  • Run I know it works, but I quite confuse myself with the types :) of way, grateful!

6

Knowing that perfect squares are located at well-defined intervals:

  • Q1 = 0 + 1 = 1
  • Q2 = 1 + 3 = 4
  • Q3 = 4 + 5 = 9
  • Q4 = 9 + 7 = 16
  • Q5 = 16 + 9 = 25

Simplifying:

  • Q1 = 1
  • Qn = Qn-1 + 2n - 1

We can print the sequence, without depending on sqrt, what makes this the fastest way (only... it’s not always like this) to process such a sequence:

function QuadradoPerfeito(n) {
  var out = '';
  var x = 1;
  for (var i = 3; ; i += 2)
  for (var j = 0; j < i; j++) {
    if (x > n) return out;
    out += x + (j == 0 ? ' QUADRADO PERFEITO' : '') + '<br>';
    x++;
  }
}

document.body.innerHTML = QuadradoPerfeito(100);

But two nested ties... is not slower?

Despite having two nested loops, the total amount of calculations made is linear, because the output condition is on the variable x, which is increased in every passage.

In addition, the browser is able to optimize these nested loops in such a way, that even redoing the code with a single loop, the result is even slower, however it is much easier to understand the logic.

There goes a simulation of what happens when calling the method with n=20:

i=3:
  j=0: x=1 // QUADRADO PERFEITO
  j=1: x=2
  j=2: x=3
i=5:
  j=0: x=4 // QUADRADO PERFEITO
  j=1: x=5
  j=2: x=6
  j=3: x=7
  j=4: x=8
i=7:
  j=0; x=9 // QUADRADO PERFEITO
  j=1; x=10
  j=2; x=11
  j=3; x=12
  j=4; x=13
  j=5; x=14
  j=6; x=15
i=9:
  j=0; x=16 // QUADRADO PERFEITO
  j=1; x=17
  j=2; x=18
  j=3; x=19
  j=4; x=20

 

Single loop version, provided by @Bacco

Based on the comments on the amount of loops, @Bacco made a version that has exactly the same logic, but in a single loop.

But beware: this unique tie is no better in terms of performance than the double ties presented at the beginning of this answer! This version is to help people with less experience view logic.

function QuadradoPerfeito(n) {
  var out = '';
  var x = 1;
  var s = 1;
  var i;

  for ( i = 1; i <= n ; i++ ) {
    out += i;
    if ( i == x ) {
      out += ' QUADRADO PERFEITO';
      x = i + (s += 2 );
    }
    out += ' <br>';
  }
  return out;
}

document.body.innerHTML = QuadradoPerfeito(100);
  • Sounds like good code, but tell me, why would two loops be better than Math.sqrt? How are you sure Math.sqrt is slower? Have you made any unit test? :)

  • What matters is not the amount of nested loops, but the total of passages that these loops do. Note that the second loop is conditioned to the first. Also, the return condition is on the variable x, which is incremented in the innermost loop, so the total passages made will be exactly the same value as n.

  • I only said this so as not to sound like opinion, with "100" actually your example is faster (but only 3% according to my test), apparently yours was a little faster on most Ecmascript engines: jsperf.com/loop-vs-Math-sqrt

  • @Guilhermenascimento I took a look there at jsperf... here runs faster sometimes not... but most of the time the version with sqrt is slower. The weirdest thing is that I made a single loop version, and this version was the slowest one here: http://jsperf.com/loop-vs-math-sqrt/3

  • 1

    The V8 engine of Ecmascript must have a cache structure or "forecast", so this must be the reason for different results in certain situations, as well as can be a lock by running several events simultaneously.

  • With so many Javascript engines it’s really hard to say "faster"... it’s there as an alternative so.

  • 1

    @Bacco edited the answer including the single loop, with due credit... so the answers get more organized. Thanks for the complementation.

Show 2 more comments

-2

window.onload = Quadradoperfeito

function Quadradoperfeito {

var numero;
var calculo;

for (numero=1; numero<=100; numero++)
{

calculo = Math.sqrt( numero );

if ( calculo == Math.floor( calculo ) )
{
document.write( numero + ' QUADRADO PERFEITO<br>');
}
 else 
{
document.write(numero + '<br>');
  }

}
}
  • 2

    Thanks for the collaboration, it seems the same answer from @Bacco, only it doesn’t work, can you say what’s different about it? Thank you :)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.