بازگشت به درس

مجموع را تا عدد داده شده پیدا کنید

اهمیت: 5

یک تابع sumTo(n) بنویسید که جمع اعداد 1 + 2 + ... + n را حساب می‌کند.

برای مثال:

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

3 نوع راه‌حل بنویسید:

  1. با استفاده از یک حلقه for.
  2. با استفاده از بازگشت، چون به ازای n > 1 داریم sumTo(n) = n + sumTo(n-1).
  3. با استفاده از فرمول تصاعد حسابی.

یک مثال از نتیجه:

function sumTo(n) { /*... کد شما ... */ }

alert( sumTo(100) ); // 5050

پی‌نوشت: کدام راه‌حل سریع‌ترین است؟ کدام کندترین؟ چرا؟

پی‌نوشت دوم: آیا می‌توانیم از بازگشت برای محاسبه sumTo(100000) استفاده کنیم؟

راه‌حل با استفاده از حلقه:

function sumTo(n) {
  let sum = 0;
  for (let i = 1; i <= n; i++) {
    sum += i;
  }
  return sum;
}

alert( sumTo(100) );

راه‌حل با استفاده از بازگشت:

function sumTo(n) {
  if (n == 1) return 1;
  return n + sumTo(n - 1);
}

alert( sumTo(100) );

راه‌حل با استفاده از فرمول sumTo(n) = n*(n+1)/2:

function sumTo(n) {
  return n * (n + 1) / 2;
}

alert( sumTo(100) );

پی‌نوشت: به طور طبیعی، فرمول سریع‌ترین راه‌حل است. این فرمول فقط از 3 عمل برای هر عدد n استفاده می‌کند. ریاضی کمک می‌کند!

راه‌حل حلقه از نظر سرعت دوم است. در هر دو نوع بازگشتی و حلقه ما اعداد یکسانی را جمع می‌زنیم. اما بازگشت، فراخوانی‌های تودرتو و مدیریت پشته اجرا را دخیل می‌کند. همچنین منابع بیشتری مصرف می‌کند پس کندتر است.

پی‌نوشت دوم: بعضی از موتورها از بهینه‌سازی «فراخوانی دنباله‌دار» پشتیبانی می‌کنند: اگر یک فراخوانی بازگشتی دقیقا آخرین فراخوانی در تابع باشد، سپس تابع بیرونی نیازی نخواهد داشت که اجرا شدن را ادامه دهد پس موتور نیازی ندارد که زمینه‌اجرای آن را به یاد بسپارد. این موضوع بار را از دوش حافظه برمی‌دارد پس محاسبه ممکن می‌شود. اما اگر موتور جاوااسکریپت از بهینه‌سازی فراخوانی دنباله‌دار پشتیبانی نکند (اکثر آنها پشتیبانی نمی‌کنند)، یک ارور ایجاد می‌شود: از حداکثر اندازه پشته گذشتیم، چون معمولا یک محدودیت برای کل اندازه پشته وجود دارد.