Sonlar
JavaScript'ning asosiy sonli tipi bo‘lgan Number
tipi ham butun sonlarni ifodalash, ham haqiqiy sonlarni taqriban hisoblash uchun xizmat qiladi. JavaScript sonlarni ifodalash uchun IEEE 754 standarti1 bilan belgilangan 64 bitli suzuvchi nuqtali (floating-point
) formatdan foydalanadi. Bu format ±1.7976931348623157 × 10³⁰⁸
gacha bo‘lgan ulkan va ±5 × 10⁻³²⁴
gacha bo‘lgan juda kichik sonlarni ifodalash imkonini beradi.
JavaScript'ning son formati −9,007,199,254,740,992
(−2⁵³) dan 9,007,199,254,740,992
(2⁵³) gacha bo‘lgan barcha butun sonlarni (shu sonlarning o‘zini ham qo‘shgan holda) mutlaqo aniq ifodalash imkonini beradi. Agar bundan katta butun sonlar bilan ishlasangiz, ularning oxirgi raqamlarida aniqlik yo‘qolishi mumkin. Shuni ta’kidlash joizki, JavaScript’dagi ba’zi amallar (masalan, massivlarni indekslash va 4-bobda yoritilgan bitli operatorlar) 32 bitli butun sonlar bilan bajariladi. Bundan ham katta butun sonlarni mutlaqo aniq ifodalash zarur bo‘lsa, §3.2.5-bo‘limga qarang.
JavaScript dasturi kodida to‘g‘ridan-to‘g‘ri yozilgan son sonli literal deb ataladi. JavaScript sonli literallarning bir necha formatini qo‘llab-quvvatlaydi va ular keyingi bo‘limlarda yoritilgan. Shuni ham aytib o‘tish kerakki, har qanday sonli literal oldidan minus (-
) belgisi kelishi mumkin va bu uni manfiy songa aylantiradi.
Butun sonli literallar
JavaScript dasturida o‘nlik sanoq tizimidagi (base-10
) butun son shunchaki raqamlar ketma-ketligi sifatida yoziladi. Masalan:
O‘nlik sanoq tizimidagi butun sonli literallardan tashqari, JavaScript o‘n oltilik (hexadecimal, base-16
) qiymatlarni ham tushunadi. O‘n oltilik literal 0x
yoki 0X
bilan boshlanadi va undan keyin o‘n oltilik raqamlar ketma-ketligi keladi. O‘n oltilik raqam — bu 0 dan 9 gacha bo‘lgan raqamlardan biri yoki 10 dan 15 gacha bo‘lgan qiymatlarni ifodalovchi a (yoki A) dan f (yoki F) gacha bo‘lgan harflardir. Quyida o‘n oltilik butun sonli literallarga misollar keltirilgan:
ES6 va undan keyingi versiyalarda butun sonlarni 0x
o‘rniga 0b
va 0o
(yoki 0B
va 0O
) prefikslari yordamida ikkilik (binary, base-2
) yoki sakkizlik (octal, base-8
) sanoq tizimlarida ham ifodalash mumkin:
Suzuvchi nuqtali literallar
Suzuvchi nuqtali literallar o‘nli kasr nuqtasiga ega bo‘lishi mumkin; ular haqiqiy sonlar uchun an’anaviy sintaksisdan foydalanadi. Haqiqiy qiymat sonning butun qismi, undan keyin keladigan o‘nli kasr nuqtasi va sonning kasr qismi sifatida ifodalanadi.
Suzuvchi nuqtali literallarni eksponensial yozuv yordamida ham ifodalash mumkin: bunda haqiqiy sondan keyin e
(yoki E
) harfi, undan keyin ixtiyoriy plyus yoki minus belgisi va undan keyin butun sonli daraja ko‘rsatkichi keladi. Bu yozuv haqiqiy sonni 10 ning ko‘rsatilgan darajasiga ko‘paytirishni anglatadi.
Qisqacha aytganda, sintaksis quyidagicha:
Sonli literallarda ajratuvchilar
Uzun literallarni o‘qish uchun qulayroq bo‘lgan qismlarga ajratish uchun sonli literallar ichida pastki chiziq (_
) belgisidan foydalanishingiz mumkin:
Ushbu kitob yozilayotgan 2020-yil boshida sonli literallardagi pastki chiziqlar hali JavaScript'ning rasmiy standarti sifatida qabul qilinmagan edi. Biroq ular standartlashtirish jarayonining yuqori bosqichida turibdi va barcha asosiy brauzerlar hamda Node tomonidan implementatsiya qilingan.
JavaScript'da arifmetik amallar
JavaScript dasturlari til taqdim etadigan arifmetik operatorlar yordamida sonlar bilan ishlaydi. Bularga qo‘shish uchun +
, ayirish uchun -
, ko‘paytirish uchun *
, bo‘lish uchun /
va bo‘lgandagi qoldiqni topish uchun %
(modulo) kiradi. ES2016 versiyasi darajaga ko‘tarissh uchun **
operatorini qo‘shgan. Bu va boshqa operatorlar haqidagi to‘liq ma’lumotni 4-bobdan topishingiz mumkin.
Ushbu asosiy arifmetik operatorlardan tashqari, JavaScript Math
obyektining xossalari sifatida aniqlangan funksiyalar va konstantalar to‘plami orqali murakkabroq matematik amallarni ham qo‘llab-quvvatlaydi:
ES6 Math
obyektiga yana qo‘shimcha funksiyalar kiritgan:
Cheksizlik va nolga bo‘lish
JavaScript'da arifmetik amallar xotiradan toshib ketish (overflow), minimal qiymatdan pasayib ketish (underflow) yoki nolga bo‘lish holatlarida xatolik yuzaga keltirmaydi. Sonli amal natijasi ifodalash mumkin bo‘lgan eng katta sondan oshib ketsa (overflow), natija maxsus cheksizlik qiymati — Infinity
bo‘ladi. Xuddi shunday, manfiy qiymatning moduli ifodalash mumkin bo‘lgan eng katta manfiy sonning modulidan oshib ketsa, natija manfiy cheksizlik — -Infinity
bo‘ladi.
Cheksiz qiymatlar o‘zini siz kutgandek tutadi: ularni biror narsaga qo‘shish, ayirish, ko‘paytirish yoki bo‘lish (ehtimol ishorasi o‘zgarishi bilan) yana cheksiz qiymatni beradi.
Underflow holati sonli amal natijasi ifodalash mumkin bo‘lgan eng kichik sondan ham nolga yaqinroq bo‘lganda yuz beradi. Bunday holda, JavaScript 0 qaytaradi. Agar underflow manfiy sondan kelib chiqsa, JavaScript "manfiy nol" deb nomlanuvchi maxsus qiymatni qaytaradi. Bu qiymat oddiy noldan deyarli farq qilmaydi va JavaScript dasturchilari uni aniqlashiga kamdan-kam ehtiyoj sezadilar.
Nolga bo‘lish JavaScript'da xatolik emas: u shunchaki Infinity
yoki -Infinity
qaytaradi. Biroq bitta istisno mavjud: nolni nolga bo‘lish aniq bir qiymatga ega emas va bu amalning natijasi maxsus "son emas" (not-a-number, son emas) qiymati — NaN
bo‘ladi. NaN
, shuningdek, cheksizlikni cheksizlikka bo‘lishga harakat qilganda, manfiy sondan kvadrat ildiz olganda yoki sonli bo‘lmagan va songa o‘girib bo‘lmaydigan operandlar bilan arifmetik operatorlarni ishlatganda ham paydo bo‘ladi.
JavaScript musbat cheksizlik va "son emas" qiymatlarini saqlash uchun global Infinity
va NaN
konstantalarini oldindan belgilab qo‘ygan. Bu qiymatlarga Number
obyektining xossalari sifatida ham murojaat qilish mumkin:
NaN va manfiy nolning o‘ziga xosliklari
"Son emas" qiymatining JavaScript'da bitta g‘ayrioddiy xususiyati bor: u boshqa hech qanday qiymatga, jumladan, o‘ziga ham teng emas. Bu shuni anglatadiki, x
o‘zgaruvchisining qiymati NaN
ekanligini tekshirish uchun x === NaN
deb yoza olmaysiz. Buning o‘rniga, x != x
yoki Number.isNaN(x)
deb yozishingiz kerak. Bu ifodalar faqat va faqat x
global NaN
konstantasi bilan bir xil qiymatga ega bo‘lgandagina true
bo‘ladi.
Global isNaN()
funksiyasi Number.isNaN()
'ga o‘xshaydi. U argumenti NaN
bo‘lsa yoki argument son bo‘lmagan va songa o‘girib bo‘lmaydigan qiymat bo‘lsa, true
qaytaradi. Unga bog‘liq bo‘lgan Number.isFinite()
funksiyasi esa argumenti NaN
, Infinity
yoki -Infinity
'dan boshqa har qanday son bo‘lsa, true
qaytaradi. Global isFinite()
funksiyasi argumenti chekli son bo‘lsa yoki uni chekli songa o‘girishni imkoni bo‘lsa, true
qaytaradi.
Manfiy nol qiymati ham biroz g‘ayrioddiydir. U musbat nolga (hatto JavaScript'ning qat’iy tenglik tekshiruvida ham) teng deb topiladi. Bu shuni anglatadiki, bu ikki qiymat bo‘luvchi sifatida ishlatilganidan tashqari deyarli farqlanmaydi:
Ikkilik suzuvchi nuqtali sonlar va yaxlitlash xatoliklari
Haqiqiy sonlar cheksiz ko‘p, lekin ularning faqat cheklangan miqdorigina (aniqrog‘i, 18,437,736,874,454,810,627 tasi) JavaScript'ning suzuvchi nuqtali formati orqali mutlaqo aniq ifodalanishi mumkin. Bu shuni anglatadiki, siz JavaScript'da haqiqiy sonlar bilan ishlayotganingizda, sonning ifodalanishi ko‘pincha haqiqiy sonning o‘ziga juda yaqin bo‘lgan taqribiy qiymat bo‘ladi.
JavaScript (va deyarli barcha boshqa zamonaviy dasturlash tillari) tomonidan qo‘llaniladigan IEEE-754
suzuvchi nuqtali ifodalash usuli ikkilik (binary
) ifodalashdir. U 1/2
, 1/8
va 1/1024
kabi kasrlarni mutlaqo aniq ifodalay oladi. Afsuski, biz eng ko‘p ishlatadigan kasrlar (ayniqsa, moliyaviy hisob-kitoblarda) o‘nli kasrlardir: 1/10
, 1/100
va hokazo. Ikkilik suzuvchi nuqtali ifodalash usuli esa hatto 0.1
kabi oddiy sonni ham mutlaqo aniq ifodalay olmaydi.
JavaScript sonlari yetarlicha katta aniqlikka ega va 0.1
ni juda yaqin taqribiylikda ifodalay oladi. Ammo bu sonni mutlaqo aniq ifodalab bo‘lmasligi muammolarga olib kelishi mumkin. Quyidagi kodni ko‘rib chiqing:
Yaxlitlash xatoligi sababli, .3 va .2 ning taqribiy qiymatlari orasidagi farq, .2 va .1 ning taqribiy qiymatlari orasidagi farq bilan bir xil emas. Shuni tushunish muhimki, bu muammo faqat JavaScript'ga xos emas: u ikkilik suzuvchi nuqtali sonlardan foydalanadigan har qanday dasturlash tiliga ta’sir qiladi. Shuningdek, e’tibor bering, yuqoridagi kodda x
va y
qiymatlari bir-biriga va to‘g‘ri qiymatga juda yaqin. Hisoblangan bu qiymatlar deyarli har qanday maqsad uchun yetarlidir; muammo faqat qiymatlarni tenglikka tekshirishga harakat qilganimizda yuzaga keladi.
Agar bu kabi suzuvchi nuqtali taqribiyliklar dasturlaringizda muammo tug‘dirsa, masshtablangan butun sonlardan foydalanishni ko‘rib chiqing. Masalan, pul qiymatlari bilan ishlaganda, ularni kasrli dollar sifatida emas, balki butun sonli sentlar sifatida boshqarishingiz mumkin.
BigInt
yordamida ixtiyoriy aniqlikdagi butun sonlar
JavaScript'ning ES2020'da kiritilgan eng yangi xususiyatlaridan biri bu BigInt
deb nomlanuvchi yangi sonli tipdir. 2020-yil boshiga kelib, u Chrome, Firefox, Edge va Node'da implementatsiya qilingan, Safari'da esa implementatsiya jarayoni davom etmoqda. Nomidan ko‘rinib turganidek, BigInt
— bu qiymatlari butun sonlardan iborat bo‘lgan sonli tip. Bu tip JavaScript'ga asosan boshqa ko‘plab dasturlash tillari va API'lar bilan moslik uchun talab etiladigan 64 bitli butun sonlarni ifodalash imkoniyatini berish uchun qo‘shilgan. Lekin agar sizga juda katta sonlar bilan ishlash kerak bo‘lsa, BigInt
qiymatlari minglab, hatto millionlab raqamlarga ega bo‘lishi mumkin. (Biroq shuni yodda tutingki, BigInt
implementatsiyalari kriptografiya uchun mos emas, chunki ular vaqtga bog‘liq hujumlarni (timing attacks
) oldini olishga harakat qilmaydi.)
BigInt
literallari raqamlar ketma-ketligi va undan keyin keladigan kichik n
harfi bilan yoziladi. Standart holatda ular o‘nlik sanoq tizimida bo‘ladi, lekin ikkilik, sakkizlik va o‘n oltilik BigInt
'lar uchun 0b
, 0o
va 0x
prefikslaridan foydalanishingiz mumkin:
Siz BigInt()
funksiyasidan oddiy JavaScript sonlari yoki satrlarini BigInt qiymatlariga o‘zgartirish uchun foydalanishingiz mumkin:
BigInt
qiymatlari bilan arifmetik amallar oddiy JavaScript sonlari bilan ishlashga o‘xshaydi, faqat bo‘lish amali har qanday qoldiqni tashlab yuboradi va pastga qarab (nolga tomon) yaxlitlaydi:
Standart +
, -
, *
, /
, %
va **
operatorlari BigInt
bilan ishlasa-da, shuni tushunish muhimki, BigInt
tipidagi operandlarni oddiy sonli operandlar bilan aralashtirib ishlata olmaysiz. Bu dastlab chalkash tuyulishi mumkin, lekin buning jiddiy sababi bor. Agar bir sonli tip boshqasidan umumiyroq bo‘lganida, aralash operandlar bilan arifmetikani shunchaki umumiyroq tipdagi qiymatni qaytaradigan qilib belgilash oson bo‘lardi. Lekin bu ikki tipdan hech biri boshqasidan umumiyroq emas: BigInt
haddan ortiq katta qiymatlarni ifodalay oladi, bu uni oddiy sonlardan umumiyroq qiladi. Ammo BigInt
faqat butun sonlarni ifodalay oladi, bu esa oddiy JavaScript son tipini umumiyroq qiladi. Bu muammoni hal qilishning iloji yo‘q, shuning uchun JavaScript arifmetik operatorlarga aralash operandlarni ishlatishga ruxsat bermaslik orqali bu muammoni chetlab o‘tadi.
Taqqoslash operatorlari esa, aksincha, aralash sonli tiplar bilan ishlay oladi (lekin ==
va ===
orasidagi farq haqida ko‘proq bilish uchun §3.9.1-bo‘limga qarang):
Bitli (Bitwise) operatorlar (§4.8.3-bo‘limda yoritilgan) odatda BigInt
operandlari bilan ishlaydi. Biroq Math
obyektining hech bir funksiyasi BigInt
operandlarini qabul qilmaydi.
Sanalar va vaqtlar
JavaScript sanalar va vaqtlarni ifodalovchi sonlarni ko‘rsatish va ular ustida amallar bajarish uchun oddiy Date
klassini taqdim etadi. JavaScript Date
'lari obyektlardir, lekin ular bir vaqtning o‘zida 1970-yil, 1-yanvardan beri o‘tgan millisoniyalar sonini belgilovchi vaqt belgisiga (timestamp
) — ya’ni, sonli ifodaga ham ega:
Date
klassi va uning metodlari §11.4-bo‘limda batafsil yoritilgan. Lekin biz Date
obyektlarini JavaScript tiplarini o‘zgartirish tafsilotlarini ko‘rib chiqayotganimizda, §3.9.3-bo‘limda yana bir bor uchratamiz.
-
Bu Java, C++ va ko‘pchilik zamonaviy dasturlash tillaridagi
double
tipidagi sonlar uchun qo‘llaniladigan formatdir. ↩