Suma todos los números hasta el elegido
Escribe una función sumTo(n)
que calcule la suma de los números 1 + 2 + ... + n
.
Por ejemplo:
sumTo(1) = 1
sumTo(2) = 2 + 1 = 3
sumTo(3) = 3 + 2 + 1 = 6
sumTo(4) = 4 + 3 + 2 + 1 = 10
...
sumTo(100) = 100 + 99 + ... + 2 + 1 = 5050
Escribe 3 soluciones diferentes:
- Utilizando un bucle
for
. - Usando la recursividad, pues
sumTo(n) = n + sumTo(n-1)
paran > 1
. - Utilizando la fórmula de progresión aritmética.
Un ejemplo del resultado:
function sumTo(n) { /*... tu código ... */ }
alert( sumTo(100) ); // 5050
P.D. ¿Qué variante de la solución es la más rápida? ¿Y la más lenta? ¿Por qué?
P.P.D. ¿Podemos usar la recursión para contar sumTo(100000)
?
La solución usando un bucle:
function sumTo(n) {
let sum = 0;
for (let i = 1; i <= n; i++) {
sum += i;
}
return sum;
}
alert( sumTo(100) );
La solución usando recursividad:
function sumTo(n) {
if (n == 1) return 1;
return n + sumTo(n - 1);
}
alert( sumTo(100) );
La solución usando la fórmula: sumTo(n) = n*(n+1)/2
:
function sumTo(n) {
return n * (n + 1) / 2;
}
alert( sumTo(100) );
P.D. Naturalmente, la fórmula es la solución más rápida. Utiliza solo 3 operaciones para cualquier número n
¡Las matemáticas ayudan!
La variación con el bucle es la segunda en términos de velocidad. Tanto en la variante recursiva como en el bucle sumamos los mismos números. Pero la recursión implica llamadas anidadas y gestión de la pila de ejecución. Eso también requiere recursos, por lo que es más lento.
P.P.D. Algunos motores admiten la optimización de “tail call”: si una llamada recursiva es la última en la función, sin cálculo extra, entonces la función externa no necesitará reanudar la ejecución, por lo que el motor no necesita recordar su contexto de ejecución. Eso elimina la carga en la memoria. Pero si el motor de JavaScript no soporta la optimización “tail call” (la mayoría no lo hace), entonces habrá un error: tamaño máximo de la pila excedido, porque generalmente hay una limitación en el tamaño total de la pila.