اعداد و ریاضیات

نوع Number، ویژگی‌ها و متدهای آن، آبجکت Math، گرد کردن، اعداد تصادفی، BigInt، NaN و Infinity و قالب‌بندی اعداد.

نوع داده Number در جاوا اسکریپت

در جاوا اسکریپت برخلاف زبان‌های دیگر فقط یک نوع عدد وجود دارد: Number. این نوع بر اساس استاندارد IEEE 754 (دقت دومتغیره / Double Precision) پیاده‌سازی شده و می‌تواند هم اعداد صحیح و هم اعشاری را نگه دارد.

const integer = 42;        // عدد صحیح
const decimal = 3.14;       // عدد اعشاری
const negative = -17;       // عدد منفی
const exponent = 2e3;       // 2000 (نمایش علمی)
const hex = 0xff;           // 255 (مبنای 16)
const octal = 0o377;        // 255 (مبنای 8)
const binary = 0b11111111;  // 255 (مبنای 2)

اعداد صحیح امن (Safe Integers) در محدوده -(2^53 - 1) تا (2^53 - 1) یعنی از Number.MIN_SAFE_INTEGER تا Number.MAX_SAFE_INTEGER قرار دارند.

ویژگی‌های Number

آبجکت Number چندین ثابت (Constant) مفید دارد:

Number.MAX_VALUE       // بزرگ‌ترین عدد ممکن ≈ 1.797e+308
Number.MIN_VALUE        // کوچک‌ترین عدد مثبت ≈ 5e-324
Number.MAX_SAFE_INTEGER // 9007199254740991 (2^53 - 1)
Number.MIN_SAFE_INTEGER // -9007199254740991
Number.EPSILON          // فاصله بین 1 و نزدیک‌ترین عدد بعدی
Number.POSITIVE_INFINITY // Infinity
Number.NEGATIVE_INFINITY // -Infinity
Number.NaN              // NaN (Not a Number)

متدهای Number

متدهای بررسی اعداد که هیچ تبدیلی انجام نمی‌دهند:

// بررسی صحیح بودن:
Number.isInteger(42)      // true
Number.isInteger(42.5)    // false

// بررسی امن بودن:
Number.isSafeInteger(2 ** 53)     // false — خارج از محدوده امن
Number.isSafeInteger(2 ** 53 - 1) // true

// بررسی NaN:
Number.isNaN(NaN)     // true
Number.isNaN("hello") // false — برخلاف isNaN سراسری!

// بررسی متناهی بودن:
Number.isFinite(42)       // true
Number.isFinite(Infinity) // false
Number.isFinite("42")     // false — تبدیل نمی‌کند
تفاوت مهم: Number.isNaN() فقط اگر مقدار واقعاً NaN باشد true می‌دهد، اما isNaN() سراسری ابتدا مقدار را به عدد تبدیل می‌کند: isNaN("hello") برابر true است چون "hello" به NaN تبدیل می‌شود!

تبدیل رشته به عدد

// parseInt — فقط بخش صحیح را می‌گیرد:
parseInt("42px")     // 42
parseInt("3.99")     // 3
parseInt("ff", 16)   // 255 — با مبنای 16

// parseFloat — اعشار را نگه می‌دارد:
parseFloat("3.14abc") // 3.14
parseFloat("2.5e3")   // 2500

// Number — کل رشته باید عدد باشد:
Number("42")    // 42
Number("42px")  // NaN
Number("")      // 0
Number("  7 ")  // 7 — فاصله‌ها را نادیده می‌گیرد

// عملگر یکانی + :
+"42"   // 42
+"3.14" // 3.14
+"abc"  // NaN

آبجکت Math

Math یک آبجکت درونی با توابع و ثابت‌های ریاضی است. توجه کنید که Math constructor نیست و نباید new Math() نوشت.

Math.PI    // π ≈ 3.141592653589793
Math.E     // عدد e ≈ 2.718281828459045
Math.LN2   // لگاریتم طبیعی 2
Math.SQRT2 // جذر 2

گرد کردن اعداد

Math.round(4.5)   // 5  — گرد کردن به نزدیک‌ترین
Math.round(4.4)   // 4
Math.round(-4.5)  // -4 — نکته: .5 به سمت بزرگ‌تر می‌رود

Math.floor(4.9)   // 4  — به سمت پایین
Math.floor(-4.1)  // -5 — منفی‌ها به سمت منفی‌تر!

Math.ceil(4.1)    // 5  — به سمت بالا
Math.ceil(-4.9)   // -4

Math.trunc(4.9)   // 4  — حذف اعشار
Math.trunc(-4.9)  // -4 — فقط قسمت صحیح
برای گرد کردن اعشاری به تعداد مشخص رقم: Math.round(1.005 * 100) / 100 یا بهتر: Number(1.005.toFixed(2))

اعداد تصادفی

// عدد تصادفی بین 0 (شامل) و 1 (بدون آن):
Math.random() // مثلاً 0.7231

// عدد صحیح تصادفی بین min و max (هر دو شامل):
function randomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}
randomInt(1, 6) // تاس — 1 تا 6

// انتخاب تصادفی از آرایه:
const items = ["سنگ", "کاغذ", "قیچی"];
const randomItem = items[Math.floor(Math.random() * items.length)];

حداقل و حداکثر، توان و لگاریتم

Math.max(3, 7, 2, 9, 4) // 9
Math.min(3, 7, 2, 9, 4) // 2

// با آرایه (با Spread):
const nums = [3, 7, 2, 9];
Math.max(...nums) // 9

// توان:
Math.pow(2, 10) // 1024
2 ** 10         // 1024 — روش مدرن‌تر

// جذر:
Math.sqrt(144) // 12
Math.cbrt(27)  // 3 — جذر مکعب

// قدرمطلق و علامت:
Math.abs(-5)  // 5
Math.sign(-3) // -1

// لگاریتم:
Math.log(Math.E)  // 1 — لگاریتم طبیعی
Math.log2(1024)   // 10
Math.log10(1000)  // 3

// توابع مثلثاتی (رادیان!):
Math.sin(Math.PI / 2) // 1
Math.cos(0)           // 1
Math.tan(0)           // 0
Math.hypot(3, 4)      // 5 — جذر مجموع مربعات

مشکل اعشار و دقت اعداد

به دلیل نمایش دودویی (Binary) اعداد، برخی محاسبات اعشاری نتیجه غیرمنتظره می‌دهند:

0.1 + 0.2            // 0.30000000000000004 (!)
0.1 + 0.2 === 0.3    // false (!)

// راه‌حل 1: مقایسه با خطای مجاز:
Math.abs(0.1 + 0.2 - 0.3) < Number.EPSILON // true

// راه‌حل 2: کار با سنتی به جای تومان اعشاری:
const price1 = 1050; // سنتی
const price2 = 275;  // سنتی
const total = (price1 + price2) / 100; // 13.25 — دقیق
هرگز برای مبالغ مالی از اعداد اعشاری مستقیم استفاده نکنید! یا به واحد کوچک‌تر (ریال/سنتی) تبدیل کنید یا از کتابخانه‌هایی مثل decimal.js استفاده کنید.

NaN — Not a Number

NaN مقدار ویژه‌ای است که نتیجه عملیات ریاضی نامعتبر است. خاصیت عجیب آن این است که با خودش هم برابر نیست:

NaN === NaN   // false (!)
typeof NaN    // "number" (!)

// منابع تولید NaN:
"abc" * 2       // NaN
Math.sqrt(-1)   // NaN
Infinity - Infinity // NaN
parseInt("xyz") // NaN

// تشخیص:
Number.isNaN(x) // روش صحیح
x !== x         // ترفند قدیمی — فقط NaN این‌طور است

Infinity — بی‌نهایت

1 / 0           // Infinity
-1 / 0          // -Infinity
Number.MAX_VALUE * 2 // Infinity

// محاسبات با بی‌نهایت:
Infinity + 1    // Infinity
Infinity * 0    // NaN
Infinity / Infinity // NaN

isFinite(42)  // true
isFinite(1/0) // false

BigInt — اعداد بزرگ

برای اعداد صحیح بزرگ‌تر از محدوده امن Number از BigInt استفاده می‌شود. کافی است n به انتهای عدد اضافه شود یا از BigInt() استفاده کنید:

const big = 123456789012345678901234567890n;
const fromString = BigInt("9007199254740993");

typeof big // "bigint"

// محاسبات دقیق:
9007199254740991n + 1n   // 9007199254740992n
9007199254740991 + 1     // 9007199254740992 — نتیجه غلط!

// عملیات:
(2n ** 64n)  // 18446744073709551616n
10n / 3n     // 3n — تقسیم صحیح، اعشار حذف می‌شود!

// مقایسه (مجاز):
10n > 5    // true — BigInt با Number قابل مقایسه است
10n === 10 // false — نوع‌ها متفاوت‌اند!

// ترکیب در عملیات (خطا!):
10n + 5  // TypeError — نمی‌توان ترکیب کرد
BigInt فقط برای مقادیر بسیار بزرگ یا نیاز به دقت کامل صحیح استفاده کنید؛ برای محاسبات عادی Number سریع‌تر است و پشتیبانی گسترده‌تری دارد.

قالب‌بندی اعداد

متد toFixed() تعداد رقم اعشار را مشخص می‌کند و رشته برمی‌گرداند:

(3.14159).toFixed(2)     // "3.14"
(1.005).toFixed(2)       // "1.00"
(1234.5678).toFixed(0)   // "1235"
typeof (3.14).toFixed(1) // "string" — عدد نیست!

// toPrecision — تعداد رقم معنادار:
(123.456).toPrecision(4)  // "123.5"
(0.000123).toPrecision(2) // "0.00012"

// تبدیل به عدد دوباره:
Number((3.14159).toFixed(2)) // 3.14

قالب‌بندی محلی با Intl

// جداکننده هزارگان:
(1234567.89).toLocaleString("fa-IR") // "۱٬۲۳۴٬۵۶۷٫۸۹"
(1234567.89).toLocaleString("en-US") // "1,234,567.89"

// واحد پول:
(12500).toLocaleString("fa-IR", { style: "currency", currency: "IRR" })

// Intl.NumberFormat — برای استفاده مکرر (کارایی بیشتر):
const faNum = new Intl.NumberFormat("fa-IR");
faNum.format(1234567) // "۱٬۲۳۴٬۵۶۷"

// درصد:
new Intl.NumberFormat("fa-IR", { style: "percent" }).format(0.25)

خوانایی اعداد بزرگ

// زیرخط جداکننده برای خوانایی (ES2021):
const billion = 1_000_000_000; // 1000000000
const bytes   = 0xFF_FF_FF_FF; // 4294967295

// تبدیل امن ورودی:
function toNumber(value, fallback = 0) {
    const n = Number(value);
    return Number.isNaN(n) ? fallback : n;
}
toNumber("42")      // 42
toNumber("abc", -1) // -1 — مقدار جایگزین

جمع‌بندی

در این درس با نوع Number و همه ظرایف آن آشنا شدید: از ثابت‌ها و متدهای Number تا آبجکت Math با توابع گرد کردن، تصادفی، توان و مثلثاتی. دیدید که اعشارهای دودویی مشکل‌سازند و راه‌حل‌های آن (EPSILON و کار با واحدهای کوچک) را یاد گرفتید. با NaN و Infinity و ویژگی‌های عجیبشان آشنا شدید و BigInt را برای اعداد خیلی بزرگ شناختید. در درس بعد سراغ آرایه‌ها — پرکاربردترین ساختار داده جاوا اسکریپت — می‌رویم.

این مبحث بخشی از دوره آموزش کامل جاوا اسکریپت است.

ابزارهای مرتبط