صفر تا صد Number در جاوا اسکریپت
در استاندارد جدید، دو نوع Number در جاوا اسکریپت وجود داد:
- اعداد معمولی در جاوا اسکریپت با فرمت 64 بیتی IEEE-754 ذخیره میشوند که بهعنوان «اعداد ممیز شناور با دقت مضاعف» نیز شناخته میشود. اینها اعدادی هستند که ما بیشتر اوقات از آنها استفاده میکنیم و در این پست آموزشی میخواهیم در رابطه با آنها باهم به گفتگو بپردازیم.
- اعداد BigInt، برای نشان دادن اعداد صحیح با طول دلخواه. این اعداد نیز فرمت دیگری از اعداد در جاوا اسکریپت هستند و گاهی اوقات موردنیاز هستند، زیرا یک عدد معمولی نمیتواند با بهآسانی از 253 تجاوز کند یا کمتر از -253 باشد. ازآنجاییکه بیگینت ها در چند ناحیه خاص مورداستفاده قرار میگیرند در این مقاله آموزشی نمیتوانیم بهطور کامل در رابطه با آنها به بحث خاصی بپردازیم.
[box type=”note” align=”” class=”” width=””]ویدئو آموزشی: جاوا اسکریپت[/box]
روشهای نمایش Number در جاوا اسکریپت
تصور کنید باید 1 میلیارد بنویسیم. سادهترین راه برای نوشتن Number در جاوا اسکریپت بهصورت زیر است:
let billion = 1000000000;
همچنین میتوانیم از آندرلاین_ بهعنوان جداکننده ارقام استفاده کنیم:
let billion = 1_000_000_000;
در اینجا آندرلاین نقش جداکننده اعداد (سه رقم سه رقم) را بازی میکند و خواندن این عدد را خواناتر میکند. موتور جاوا اسکریپت بهسادگی _ بین ارقام را نادیده میگیرد و به خوانایی آن میافزاید.
در کاربرد واقعی ما سعی میکنیم از نوشتن دنبالههای طولانی صفر در اعداد خودداری کنیم. مثلاً میخواهیم از 7.3 میلیارد بهجای 7 میلیارد و 300 میلیون استفاده کنیم. همین امر برای اکثر اعداد بزرگ صادق است.
در جاوا اسکریپت، میتوانیم یک عدد را با الحاق حرف “e” به آن و تعیین تعداد صفرها آن را کوتاه کنیم. این روش را نماد علمی میگوییم و برای نمایش Number در جاوا اسکریپت از آن استفاده میکنیم. به مثال زیر توجه کنید.
let billion = 1e9; // 1 billion, literally: 1 and 9 zeroes alert( 7.3e9 ); // 7.3 billions (same as 7300000000 or 7_300_000_000)
بهعبارتدیگر، e با تعداد صفرهای دادهشده عدد را در 1 ضرب میکند.
1e3 === 1 * 1000; // e3 means *1000 1.23e6 === 1.23 * 1000000; // e6 means *1000000
این کار را میتوانیم در مقیاس اعداد کوچک نیز انجام دهیم. مثلاً 1 میکروثانیه (یک میلیونیم ثانیه) بهصورت زیر در جاوا اسکریپت قابلنمایش است.
let mсs = 0.000001;
درست مانند قبل، استفاده از “e” میتواند در این زمینه نیز کمککننده باشد. اگر میخواهیم از نوشتن صریح صفرها اجتناب کنیم، میتوانیم بهصورت زیر بنویسیم:
let mcs = 1e-6; // six zeroes to the left from 1
اگر صفرها را در 0.000001 بشماریم، 6 عدد وجود دارد؛ بنابراین طبیعتاً 1e-6 برای این عدد به کار میرود. بهعبارتدیگر، عدد منفی بعد از “e” به معنای تقسیمبر 1 با تعداد صفرهای دادهشده است:
// -3 divides by 1 with 3 zeroes
1e-3 === 1 / 1000; // 0.001
// -6 divides by 1 with 6 zeroes
1.23e-6 === 1.23 / 1000000; // 0.00000123
اعداد هگز، باینری و هشتی در جاوا اسکریپت
اعداد هگزادسیمال بهطور گسترده در جاوا اسکریپت برای نمایش رنگها، رمزگذاری کاراکترها و بسیاری موارد دیگر استفاده میشوند. طبیعتاً راه کوتاهتری برای نوشتن آنها وجود دارد: 0x و سپس عدد. در زیر به مثالهای متعددی در رابطه با Number در جاوا اسکریپت در این فرمت میپردازیم.
برای مثال:
alert( 0xff ); // 255 alert( 0xFF ); // 255 (the same, case doesn't matter)
سیستمهای اعداد باینری و اکتال بهندرت استفاده میشوند و با استفاده از پیشوندهای 0b و 0o نیز پشتیبانی میشوند:
let a = 0b11111111; // binary form of 255 let b = 0o377; // octal form of 255 alert( a == b ); // true, the same number 255 at both sides
تنها 3 سیستم عددی با چنین پشتیبانی وجود دارد. برای سیستمهای اعداد دیگر، باید از تابع parseInt استفاده کنیم (که در ادامه این مقاله به آنها شاره میکنیم).
[box type=”note” align=”” class=”” width=””]مقاله پیشنهادی: String در جاوا اسکریپت [/box]
اعداد toString(base) در js
متد num.toString(base) یک نمایش رشتهای از num Number در جاوا اسکریپت در سیستم اعداد با پایه دادهشده را برمیگرداند. برای مثال:
let num = 255; alert( num.toString(16) ); // ff alert( num.toString(2) ); // 11111111
پایه میتواند از 2 تا 36 متغیر باشد. بهطور پیشفرض این پایه 10 است.
موارد استفاده رایج برای این عبارتاند از:
- base=16 برای رنگهای هگز، رمزگذاری کاراکتر و غیره استفاده میشود، ارقام میتوانند 0..9 یا .F باشند.
- base=2 بیشتر برای اشکالزدایی عملیات بیتی است، ارقام میتوانند 0 یا 1 باشند.
- base=36 حداکثر مقدار پایه است، ارقام میتوانند 0..9 یا .Z باشند. کل الفبای لاتین برای نشان دادن یک عدد استفاده میشود. 36 زمانی مفید است که باید یک شناسه عددی طولانی را به چیزی کوتاهتر تبدیل کنیم، بهعنوانمثال برای ایجاد یک URL کوتاه. بهسادگی میتوان آن را در سیستم اعداد با پایه 36 نشان داد:
alert( 123456..toString(36) ); // 2n9c
نکته مهم: دونقطه (..) برای فراخوانی یک متد
لطفاً توجه داشته باشید که دونقطه در 123456..toString(36) اشتباه تایپی نیست. اگر بخواهیم یک متد را مستقیماً روی یک عدد فراخوانی کنیم، مانند toString در مثال بالا، باید دونقطه را بعدازآن قرار دهیم.
اگر یک نقطه را قرار دهیم: 123456.toString(36)، آنگاه خطایی وجود خواهد داشت، زیرا نحو جاوا اسکریپت به معنای قسمت اعشاری بعد از اولین نقطه است؛ و اگر یک نقطه دیگر قرار دهیم، جاوا اسکریپت میداند که قسمت اعشاری خالی است و اکنون به روش میرود. همچنین میتوانید آن را بهصورت (123456).toString(36) بنویسد.
گرد کردن اعداد در جاوا اسکریپت
یکی از پرکاربردترین عملیات هنگام کار با Number در جاوا اسکریپت، گرد کردن است. چندین عملکرد داخلی برای گرد کردن در جاوا اسکریپت وجود دارد:
- floor: گرد کردن: 3.1 میشود 3 و -1.1 میشود -2.
- ceil: گرد کردن: 3.1 میشود 4 و -1.1 میشود -1.
- round: به نزدیکترین عدد صحیح گرد میکند: 3.1 میشود 3، 3.6 میشود 4، حالت میانی: 3.5 تا 4 را نیز گرد میکند.
- trunc (توسط اینترنت اکسپلورر پشتیبانی نمیشود): هر چیزی را بعد از نقطه اعشار بدون گرد کردن حذف میکند: 3.1 میشود 3، -1.1 میشود -1.
در اینجا جدول برای خلاصه کردن تفاوتهای بین آنها آمده است:
این توابع تمام راههای ممکن برای گرد کردن Number در جاوا اسکریپت با قسمت اعشاری یک عدد را پوشش میدهند؛ اما اگر بخواهیم بعد از اعشار عدد را به عدد n-ام گرد کنیم چه؟ یعنی تعداد رقمی خاص بعد از اعشار. بهعنوانمثال، ما 1.2345 داریم و میخواهیم آن را به 2 رقم گرد کنیم و فقط 1.23 به دست آوریم.
دو راه برای این کار وجود دارد:
ضرب و تقسیم:
بهعنوانمثال، برای گرد کردن عدد به رقم دوم بعد از اعشار، میتوان عدد را در 100 ضرب کرد، تابع گرد کردن را فراخوانی کرد و سپس آن را تقسیم کرد.
let num = 1.23456;
alert( Math.round(num * 100) / 100 ); // 1.23456 -> 123.456 -> 123 -> 1.23
متد toFixed(n):
متد toFixed(n) عدد را به n رقم بعد از نقطه گرد میکند و یک نمایش رشتهای از نتیجه را برمیگرداند.
let num = 12.34;
alert( num.toFixed(1) ); // "12.3"
این به نزدیکترین مقدار، مشابه Math.round، بالا یا پایین میشود:
let num = 12.36;
alert( num.toFixed(1) ); // "12.4"
لطفاً توجه داشته باشید که نتیجه toFixed یکرشته است. اگر قسمت اعشاری کوتاهتر از مقدار موردنیاز باشد، صفرها به انتها اضافه میشوند:
let num = 12.34;
alert( num.toFixed(5) ); // "12.34000", added zeroes to make exactly 5 digits
[box type=”note” align=”” class=”” width=””]مفاله پیشنهادی: دستور break در جاوا اسکریپت [/box]
محاسبات غیردقیق در js
یک Number در جاوا اسکریپت با فرمت 64 بیتی IEEE-754 نشان داده میشود، بنابراین میتوان گفت که دقیقاً 64 بیت برای ذخیره یک عدد وجود دارد: 52 بیت از آنها برای ذخیره ارقام استفاده میشود، 11 عدد از آنها موقعیت نقطه اعشار را ذخیره میکنند (برای اعداد صحیح صفر هستند) و 1 بیت برای علامت است.
اگر یک عدد خیلی بزرگ باشد، ممکن است فضای ذخیرهسازی 64 بیتی را سرریز کند و به یک مقدار عددی ویژه Infinity تبدیل شود:
alert( 1e500 ); // Infinity
در این موارد ما اغلب دقت را از دست میدهیم. مثلاً این تست برابری را در نظر بگیرید:
alert( 0.1 + 0.2 == 0.3 ); // false
هرچند که در نگاه اول حدس بزنید جواب درست باشد، اما در کمال ناباوری جواب false را برمیگرداند.
alert( 0.1 + 0.2 ); // 0.30000000000000004
اما چرا این اتفاق میافتد؟
یک عدد به شکل دودویی در حافظه ذخیره میشود، دنبالهای از بیتها – یک و صفر؛ اما اعداد کسری مانند 0.1، 0.2 که در سیستم عددی اعشاری ساده به نظر میرسند، درواقع کسرهای بیپایان در شکل دودویی خود هستند.
0.1 چیست؟ تقسیمبر ده 1/10، یکدهم است. در سیستم اعداد اعشاری چنین اعدادی بهراحتی قابلنمایش هستند. آن را با یکسوم مقایسه کنید: 1/3. تبدیل به کسری بیپایان 0.33333(3) میشود.
فقط هیچ راهی برای ذخیره 0.1 یا دقیقاً 0.2 با استفاده از سیستم باینری وجود ندارد، همانطور که هیچ راهی برای ذخیره یکسوم بهعنوان کسر اعشاری وجود ندارد.
فرمت عددی IEEE-754 در Number در جاوا اسکریپت این مشکل را با گرد کردن به نزدیکترین عدد ممکن حل میکند. ما میتوانیم این را در عمل مشاهده کنیم:
alert( 0.1.toFixed(20) ); // 0.10000000000000000555
و وقتی دو عدد را جمع میکنیم، “تلفات دقیق” آنها جمع میشود. به همین دلیل 0.1 + 0.2 دقیقاً 0.3 نیست.
نهتنها جاوا اسکریپت همین مشکل در بسیاری از زبانهای برنامهنویسی دیگر وجود دارد. پی اچ پی، جاوا، سی، پرل، روبی دقیقاً نتیجه مشابهی دارند، زیرا بر اساس فرمت عددی یکسانی هستند.
آیا میتوانیم مشکل را حل کنیم؟ مطمئناً مطمئنترین روش گرد کردن نتیجه با کمک روش toFixed(n) است:
let sum = 0.1 + 0.2;
alert( sum.toFixed(2) ); // "0.30"
لطفاً توجه داشته باشید که toFixed همیشه یکرشته را برمیگرداند. این روش در گرد کردن Number در جاوا اسکریپت اطمینان حاصل میکند که عدد دارای 2 رقم بعد از نقطه اعشار است.
let sum = 0.1 + 0.2;
alert( +sum.toFixed(2) ); // 0.3
همچنین میتوانیم بهطور موقت اعداد را در 100 (یا یک عدد بزرگتر) ضرب کنیم تا آنها را به اعداد صحیح تبدیل کنیم یا سایر عملیات ریاضی را برای آنها انجام دهیم. با این کار نیز میتوانیم تا حدودی دقت را بالا ببریم و خطا را کاهش دهیم. به مثال زیر توجه کنید:
alert( (0.1 * 10 + 0.2 * 10) / 10 ); // 0.3
alert( (0.28 * 100 + 0.14 * 100) / 100); // 0.4200000000000001
بنابراین، رویکرد ضرب/تقسیم خطا را کاهش میدهد، اما آن را بهطور کامل حذف نمیکند.
isFinite و isNaN با Number در جاوا اسکریپت
- Infinity (و -Infinity) یک مقدار عددی خاص است که از هر چیزی بزرگتر (کمتر) است و به زبان ساده بیانگر مقدار بینهایت کوچک یا بینهایت بزرگ هستند.
- NaNنشاندهنده یک خطا است.
این نوع Number در جاوا اسکریپت دادههای عادی نیستند و برای فراخوانی به توابع خاصی نیاز دارند.
isNaN(value) آرگومان خود را به عدد تبدیل میکند و سپس آن را برای NaN بودن آزمایش میکند:
alert( isNaN(NaN) ); // true
alert( isNaN("str") ); // true
اما آیا ما به این تابع نیاز داریم؟ آیا نمیتوانیم فقط از مقایسه === NaN استفاده کنیم؟ پاسخ منفی است و ما ملزم به استفاده از آن هستیم. مقدار NaN از این نظر منحصربهفرد است که با هیچچیز ازجمله خودش برابری نمیکند:
alert( NaN === NaN ); // false
isFinite(value) آرگومان خود را به عدد تبدیل میکند و اگر یک عدد منظم باشد، نه NaN/Infinity/-Infinity، مقدار true را برمیگرداند:
alert( isFinite("15") ); // true
alert( isFinite("str") ); // false, because a special value: NaN
alert( isFinite(Infinity) ); // false, because a special value: Infinity
گاهی اوقات isFinite برای تأیید اینکه آیا یک مقدار رشته یک عدد منظم است استفاده میشود:
let num = +prompt("Enter a number", '');
// will be true unless you enter Infinity, -Infinity or not a number
alert( isFinite(num) );
لطفاً توجه داشته باشید که یکرشته خالی یا فقط بافاصله در همه توابع عددی ازجمله isFinite بهعنوان 0 در نظر گرفته میشود.
parseInt و parseFloat
تبدیل عددی با استفاده از + + یا Number() چندان روش آسانی نیست و برای موارد غیر عددی تبدیلها این روشها اصلاً امکانپذیر نیست. ما در این مقاله Number در جاوا اسکریپت روشهای parseInt و parseFloat را موردبررسی قرار میدهیم تا این کار را برای ما انجام دهد.
alert( +"100px" ); // NaN
تنها استثنا در این زمینه، اسپیسهای ابتدای یا انتهای رشته است، زیرا آنها نادیده گرفته میشوند.
اما در کاربرد واقعی ما اغلب مقادیری در واحدها داریم، مانند “100px” یا “12pt” در CSS. همچنین در بسیاری از کشورها نماد ارز بعد از مقدار میرود، مثلاً ما “19€” داریم و میخواهیم مقدار عددی را از آن استخراجکنیم. این همان کاربردی است که parseInt و parseFloat برای آن به وجود آمدهاند:
آنها یک عدد را از یکرشته استخراج میکنند. در صورت بروز یک خطا، شماره جمعآوریشده برگردانده میشود. تابع parseInt یک عدد صحیح برمیگرداند، درحالیکه parseFloat یک عدد ممیز شناور را برمیگرداند:
alert( parseInt('100px') ); // 100
alert( parseFloat('12.5em') ); // 12.5
alert( parseInt('12.3') ); // 12, only the integer part is returned
alert( parseFloat('12.3.4') ); // 12.3, the second point stops the reading
شرایطی وجود دارد که parseInt/parseFloat NaN را برمیگرداند. زمانی اتفاق میافتد که هیچرقمی قابلخواندن نباشد:
alert( parseInt('a123') ); // NaN, the first symbol stops the process
آرگومان دوم parseInt(str, radix)
تابع parseInt() یک پارامتر دوم اختیاری دارد. پایه سیستم اعداد را مشخص میکند، بنابراین parseInt همچنین میتواند رشتههای اعداد هگز، اعداد باینری و غیره را در Number در جاوا اسکریپت تجزیه کند:
alert( parseInt('0xff', 16) ); // 255
alert( parseInt('ff', 16) ); // 255, without 0x also works
alert( parseInt('2n9c', 36) ); // 123456
سایر توابع ریاضی برای اعداد در جاوا اسکریپت
جاوا اسکریپت دارای یکشی ریاضی داخلی برای Number در جاوا اسکریپت است که شامل یک کتابخانه کوچک از توابع و ثابتهای ریاضی است.
چند مثال:
Math.random()
یک عدد تصادفی از 0 تا 1 را برمیگرداند (بدون احتساب 1).
alert( Math.random() ); // 0.1234567894322
alert( Math.random() ); // 0.5435252343232
alert( Math.random() ); // ... (any random numbers)
alert( Math.random() ); // ... (any random numbers)
بزرگترین/کوچکترین را از تعداد دلخواه آرگومان برمیگرداند.
alert( Math.max(3, 5, -10, 0, 1) ); // 5
alert( Math.min(1, 2) ); // 1
Math.pow(n, power)
n را به توان دادهشده میرساند
-
alert( Math.pow(2, 10) ); // 2 in power 10 = 1024
توابع و ثابتهای بیشتری در شیء Math وجود دارد که بحث در رابطه با همه آنها در این مقاله امکانپذیر نیست.
نتیجه گیری
در این پست آموزشی از مکتب خونه ما در رابطه با Number در جاوا اسکریپت و شیوههای مختلف نمایش و استفاده از آنها باهم به گفتگو پرداختیم. اعداد در جاوا اسکریپت نوعی داده هستند که از اهمیت بسیار بالایی برخوردار هستند و لازم است که به همه جنبههای آنها برای استفاده در شرایط مختلف آگاه باشیم.
منابع مورد استفاده در این آموزش:
https://javascript.info/number
https://www.w3schools.com/js/js_number_methods.asp