Sečtěte všechna čísla až do zadaného
Napište funkci sečtiDo(n), která vypočítá součet čísel 1 + 2 + ... + n.
Například:
sečtiDo(1) = 1
sečtiDo(2) = 2 + 1 = 3
sečtiDo(3) = 3 + 2 + 1 = 6
sečtiDo(4) = 4 + 3 + 2 + 1 = 10
...
sečtiDo(100) = 100 + 99 + ... + 2 + 1 = 5050
Vytvořte 3 varianty řešení:
- Pomocí cyklu for.
- Pomocí rekurze
sečtiDo(n) = n + sečtiDo(n-1)pron > 1. - Pomocí vzorce pro aritmetickou posloupnost.
Příklad výsledku:
function sečtiDo(n) { /*... váš kód ... */ }
alert( sečtiDo(100) ); // 5050
P.S. Která varianta řešení je nejrychlejší? A nejpomalejší? Proč?
P.P.S. Můžeme použít rekurzi k výpočtu sečtiDo(100000)?
Řešení pomocí cyklu:
function sečtiDo(n) {
let součet = 0;
for (let i = 1; i <= n; i++) {
součet += i;
}
return součet;
}
alert( sečtiDo(100) );
Řešení pomocí rekurze:
function sečtiDo(n) {
if (n == 1) return 1;
return n + sečtiDo(n - 1);
}
alert( sečtiDo(100) );
Řešení pomocí vzorce: sečtiDo(n) = n*(n+1)/2:
function sečtiDo(n) {
return n * (n + 1) / 2;
}
alert( sečtiDo(100) );
P.S. Nejrychlejší řešení je pochopitelně pomocí vzorce. Pro jakékoli číslo n vykonává pouze 3 operace. Matematika pomáhá!
Druhá nejlepší co do rychlosti je varianta s cyklem. V rekurzívní i v cyklové variantě sčítáme stejná čísla, ale rekurze vyžaduje vnořená volání a správu prováděcího zásobníku. To vyžaduje další zdroje, takže je pomalejší.
P.P.S. Některé motory podporují optimalizaci „koncového volání“: je-li rekurzívní volání ve funkci úplně poslední a žádné další výpočty se neprovádějí, pak se nemusí obnovovat provádění vnější funkce, takže si motor nemusí pamatovat její prováděcí kontext. Tím se sníží paměťová zátěž. Pokud však motor JavaScriptu nepodporuje optimalizaci koncového volání (a většina motorů ji nepodporuje), nastane chyba: bude překročena maximální velikost zásobníku, protože celková velikost zásobníku je obvykle omezena.