היום למדתי: מספרים גדולים ב JavaScript
ל JavaScript יש טיפוס נתונים שנקרא number לייצוג מספרים:
> typeof(12)
'number'
משתנה מסוג number הוא בגודל 64 ביט אבל JavaScript עצמה לא משתמשת בכל 64 הביטים כדי לייצג מספרים שלמים. הערכים שמותר לייצג כמספרים הם הטווח:
> Number.MIN_SAFE_INTEGER
-9007199254740991
> Number.MAX_SAFE_INTEGER
9007199254740991
ל JavaScript יש גם טיפוס נתונים בשם bigint שיודע לייצג מספרים הרבה יותר גדולים ואנחנו יוצרים ערך מסוג bigint בעזרת הסיומת n בסוף מספר:
> typeof(12n)
'bigint'
הגודל של bigint מוגבל רק בכמות הזכרון שיש לכם על המחשב. מה קורה כשיוצאים מחוץ לטווח הבטוח? שימו לב:
> Number.MAX_SAFE_INTEGER + 1
9007199254740992
> Number.MAX_SAFE_INTEGER + 2
9007199254740992
> Number.MAX_SAFE_INTEGER + 3
9007199254740994
> Number.MAX_SAFE_INTEGER + 4
9007199254740996
> 9007199254740992 == 9007199254740993
true
נו זה היה כיף. במספרים גדולים זה כמובן לא היה קורה:
> 9007199254740992n == 9007199254740993n
false
אז למה לא להשתמש ב bigint כל הזמן? בגלל JSON כמובן:
> JSON.stringify(9007199254740992)
'9007199254740992'
> JSON.stringify(9007199254740992n)
Uncaught TypeError: Do not know how to serialize a BigInt
at JSON.stringify (<anonymous>)
בשביל ש JavaScript יהפוך מספר גדול ל JSON הוא יצטרך לכתוב ערך שאף אחד לא יוכל לקרוא. מה עושים? הופכים למחרוזת וזוכרים להמיר ל BigInt בחזרה:
BigInt(JSON.parse(JSON.stringify(90071992547409932n.toString())))
90071992547409932n
נ.ב. הסיבה שאנחנו צריכים לדבר על זה היא שאנשים עדיין שולחים לפעמים id בתור מספר במקום בתור מחרוזת וכך כשיש יותר מדי אוביקטים במערכת המזהים מתחילים להישבר. מספרים גדולים זה אחלה לחישובים אבל רוב הזמן יהיה יותר קל לדאוג תמיד לשמור את המזהים שלנו בתור מחרוזות ולא לדאוג לגודל.