4

Pues tengo una página que te pide números por pantalla (hasta pulsar -1) y te los va guardando en un array. Después al hacer clic en el botón "Mostrar" debería aparecer en el cuadro de texto la cantidad correcta de números primos que hay en dicho array. Sin embargo la función CantidadPrimos(numeros) no devuelve el resultado correcto.

Para hacer la prueba inserté los números 5, 7 y 13 y después -1. Esos tres son números primos. Pues luego sin embargo al pulsar el botón "Mostrar" en vez de 3 me sale sólo 1.

¿A qué se puede deber eso? Llevo una hora mirando el código pero no tengo ni idea de donde está el fallo.

El código es:

    //Creo un array vacío llamado "numeros" y posteriormente le voy añadiendo los números introducidos por pantalla
    var numeros = [];
    var cont = 0;
    var i = 0;
    var x = prompt("Dime un n\u00FAmero. Pulsa -1 para salir");
    while (x != -1) {
      numeros.push(x);
      x = prompt("Dime otro número. Pulsa -1 para salir");
    }



    //Función que recibe como parámetro una lista de números y muestra la cantidad de números primos
    function CantidadPrimos(list) {
      var contador = 0;
      var num = 0;
      for (x = 0; x < list.length; x++) {
        num = parseInt(list[x]);
        NumerosPrimos(num);
        if (cont == 0) {
          contador = contador + 1;
        }
      }
      document.getElementById('primos').value = contador;
    }


    //Función que recibe como parámetro un número y nos permite conocer si éste es primo o no
    function NumerosPrimos(numero) {
      if (numero > 1) {
        for (x = 2; x < numero; x++) {
          if (numero % x === 0) {
            cont = cont + 1;
          }
        }
      } else {
        cont = 1;
      }
    }


    //Función que ejecuta el resto de funciones anteriores, y que será llamada por evento onclick del botón "Mostrar" de nuestra página
    function ejecutarFuncion() {
      CantidadPrimos(numeros);
    }
  <h2>N&uacute;meros</h2>
  <!--Título de la página-->

  <p>N&uacute;meros primos: <input type="text" id="primos" name="primos"></p>
  <input type="button" value="Mostrar" onclick="ejecutarFuncion();">
BetaM
  • 30,571
  • 7
  • 32
  • 50
Pico
  • 121
  • 8
  • Quería dejar subido el código final con la solución correcta. Lo pongo como una nueva respuesta entonces? O sea le doy a "añadir respuesta" y subo el código no? – Pico May 22 '19 at 23:49
  • exacto, de esa manera indicas que quedó resuelta, nos ayudamos todos de tu aporte pues indica como se resuelve, añades el código y recibes votos que aumentan tu reputación mi estimado – BetaM May 22 '19 at 23:51

2 Answers2

2

Esto es un problema con el alcance de las variables. Si te fijas, utilizas el mismo iterador x en dos bucles diferentes. Pero como no lo estás declarando (con var o let) te encuentras con que ¡se está utilizando como una variable global! y los cambios en un bucle también afectan al otro.

Como nota aparte, deberías limitar el alcance de tus variables y funciones para evitar problemas de este tipo. Tal y como tienes tu código ahora mismo, hay varias variables globales que podrían dar problemas. Lee esta otra pregunta sobre variables globales y por qué deberías evitarlas siempre que sea posible.

¿Qué ocurre entonces? que el primer bucle (el de CantidadPrimos) se ve afectado por los cambios que se producen en el segundo bucle (el de NumerosPrimos) y se ejecuta menos veces de las que esperas (en concreto para los números 3, 5 y 7, se ejecutará sólo una vez, para el 3, y por eso recibes un 1 como resultado).

La solución rápida: añade var o let cuando uses la variable en los bucles. De ese modo se estará limitando su alcance a la función o al bucle respectivamente y no te encontrarás este problema:

for (var x = 0; x < list.length; x++) {

y

for (var x = 2; x < numero; x++) {

Aquí puedes ver tu código con ese cambio y ya funciona correctamente:

<!doctype html>
<html>

<head>
  <title>numeros</title>
</head>

<body>
  <h2>N&uacute;meros</h2>
  <!--Título de la página-->

  <p>N&uacute;meros primos: <input type="text" id="primos" name="primos"></p>
  <input type="button" value="Mostrar" onclick="ejecutarFuncion();">


  <!--Comienza código javascript-->
  <script>
    //Creo un array vacío llamado "numeros" y posteriormente le voy añadiendo los números introducidos por pantalla
    var numeros = [];
    var cont = 0;
    var i = 0;
    var x = prompt("Dime un n\u00FAmero. Pulsa -1 para salir");
    while (x != -1) {
      numeros.push(x);
      x = prompt("Dime otro número. Pulsa -1 para salir");
    }


    //Función que recibe como parámetro una lista de números y muestra la cantidad de números primos
    function CantidadPrimos(list) {
      var contador = 0;
      var num = 0;
      for (var x = 0; x < list.length; x++) {
        num = parseInt(list[x]);
        cont = 0;
        NumerosPrimos(num);
        if (cont == 0) {
          contador = contador + 1;
        }
      }
      document.getElementById('primos').value = contador;
    }


    //Función que recibe como parámetro un número y nos permite conocer si éste es primo o no
    function NumerosPrimos(numero) {
      if (numero > 1) {
        for (var x = 2; x < numero; x++) {
          if (numero % x === 0) {
            cont = cont + 1;
          }
        }
      } else {
        cont = 1;
      }
    }


    //Función que ejecuta el resto de funciones anteriores, y que será llamada por evento onclick del botón "Mostrar" de nuestra página
    function ejecutarFuncion() {
      CantidadPrimos(numeros);
    }
  </script>

</body>

</html>
Alvaro Montoro
  • 48,157
  • 26
  • 100
  • 179
  • Gracias por tu aportación, y sí, lo que comentas era un tema donde estaba fallando (soy un novato en javascript y en estas cosas se nota). Sin embargo, acabo de darme cuenta que ese nuevo código que me has puesto tampoco funciona correctamente en todos los supuestos. En el supuesto que yo te comente de un array con los números 5,7 y 13, estás metiendo tres números primos seguidos, y por eso funciona correctamente. – Pico May 22 '19 at 23:10
  • @Pico es el mismo problema. Estás usando variables globales que no se están reinicializando correctamente. Deberías dejar de usar variables globales para evitar estos problemas. Una solución para lo que comentas es resetear el valor de `cont` a 0 antes de llamar a la función `NumerosPrimos`. He actualizado el código de la respuesta para que funcione. – Alvaro Montoro May 22 '19 at 23:14
  • Pero de nuevo: esto es un parche para corregir tu código con los mínimos cambios. Idealmente deberías _refactorizar_ el código para evitar las variables globales. – Alvaro Montoro May 22 '19 at 23:14
  • Es mi primer día aquí y me estoy liando bastante con las normas de la página, sólo quería decirte que gracias por tu aporte y que ya he dado con la solución al problema, que efectivamente es lo que tú comentas. En la función CantidadPrimos(list), en cada pasada del bucle for hay que actualizar la variable cont a 0 justo antes de llamar al método NumerosPrimos(numero). Y así ya funciona correcto. – Pico May 22 '19 at 23:25
  • @Pico Te doy la bienvenida! Tu pregunta está muy bien para ser la primera (en serio, está muy completa: con descripción del problema y código). Me alegra que la respuesta te sirviera :) – Alvaro Montoro May 22 '19 at 23:27
  • Muchas gracias por tu ayuda, arriba dejo el código actualizado con la solución final por si a alguien le sirve. – Pico May 22 '19 at 23:29
1

Aquí dejo el código final con la solución correcta. Al final sólo faltaba actualizar a 0 el valor de la variable cont en cada pasada del bucle for (dentro de la función CantidadPrimos(list). Y hacerlo justo antes de llamar al método NumerosPrimos(numero). Y con eso ya funciona correctamente.

 
<script>

    var numeros = [];
    var i = 0;
    var cont = 0;
        var x=prompt("Dime un n\u00FAmero. Pulsa -1 para salir");
        while(x!=-1){
            numeros.push(x);
            x = prompt("Dime otro número. Pulsa -1 para salir");           
        }

        
    
    //Función que recibe como parámetro una lista de números y muestra la cantidad de números primos
    function CantidadPrimos(list){
        var contador = 0;
        var num = 0;
        for(var x=0;x<list.length;x++){
            num = parseInt(list[x]);
            cont = 0;
            NumerosPrimos(num);
            if(cont==0){
                contador+=1;
            }
        }
        document.getElementById('primos').value=contador;            
    }


    //Función que recibe como parámetro un número y nos permite conocer si éste es primo o no
    function NumerosPrimos(numero){
        if(numero>1){                                      
            for(var x=2;x<numero;x++){
                if (numero%x==0){
                    cont+=1;
                }
            }
        }else{
            cont = 1;
        }           
    }


    //Función que ejecuta el resto de funciones anteriores, y que será llamada por evento onclick del botón "Mostrar" de nuestra página
    function ejecutarFuncion(){
        
        CantidadPrimos(numeros);
        }

</script>
<body>

  <h2>N&uacute;meros</h2> <!--Título de la página-->            
  <p>N&uacute;meros primos: <input type="text" id="primos" name="primos"></p>
  <input type="button" value="Mostrar" onclick="ejecutarFuncion();">

</body>
Pico
  • 121
  • 8