ניסוי: מספרים גדולים ב JavaScript

12/05/2024

הקוד הבא מחשב סכום ספרות של מספר:

function sumOfDigits(n) {
  let sum = 0;
  while (n > 0) {
    sum += n % 10;
    n = Math.floor(n / 10);
  }
  return sum;
}

אני אפילו יכול לשלב אותו בתוכנית למשל עם הקוד הזה הוא מסתכל על אלמנט input וכל פעם שיש שינוי מחשב את סכום הספרות וכותב את הסכום חזרה למסך:

const input = document.querySelector('input');
input.addEventListener('input', (e) => {
  const result = sumOfDigits(Number(e.target.value));
  document.querySelector('#result').textContent = result;
});

אפשר לראות אותו בפעולה בקודפן בקישור: https://codepen.io/ynonp/pen/XWwJJmw?editors=1010

אבל מעניין לשים לב כמה קל לשבור אותו. אם אני מקליד את המספר 9999999999999999 בתיבת הטקסט אני מקבל שסכום הספרות הוא 1. ג'אווהסקריפט אפילו לא חושב שזה דורש להציג שגיאה או אזהרה בקונסול, לדעתו זה ברור שהמספר שלי גדול מדי בשביל חישובים עם Number.

מה עושים? עוברים לעבוד עם מספרים שלמים גדולים - BigInt. מספר גדול מאותחל דרך הבנאי BigInt או באמצעות הסיומת n כלומר כל אלה הם מספרים גדולים:

const n1 = BigInt(9007199254740991);
const n2 = BigInt(3);
const n3 = 10n;

חישובים עם מספרים גדולים יכולים לשלב רק מספרים גדולים אחרים, כלומר אתם לא יכולים לסכום מספר גדול עם מספר Number רגיל, ואי אפשר לשלוח את המספרים הגדולים לפונקציות של המודול Math. אם אנחנו מוכנים לחיות עם המגבלות האלה נוכל לשכתב את הדוגמה כדי שתחשב את סכום הספרות של מספר בכל אורך:

function sumOfDigits(n) {
  let sum = 0n;
  while (n > 0) {
    sum += n % 10n;
    n = n / 10n;
  }
  return sum;
}

const input = document.querySelector('input');
input.addEventListener('input', (e) => {
  const result = sumOfDigits(BigInt(e.target.value));
  document.querySelector('#result').textContent = result;
});

נשים לב לשינויים: הערך שנשלח לפונקציה הוא עכשיו BigInt ונוצר על ידי הבנאי BigInt, גם המספרים הקטנים שלוקחים חלק בחישוב הומרו ל BigInt בעזרת הסיומת n והורדתי את השימוש ב Math.floor כי חילוק מספרים שלמים גדולים מחזיר תוצאה בשלמים. זאת הגירסה המתוקנת בקודפן ואתם יכולים לראות שהיא כבר מצליחה לחשוב סכום ספרות של כל מספר:

https://codepen.io/ynonp/pen/wvbBBBP?editors=1010