Пошук уроків, статей та іншого контенту
Об'єкт Math, форматування чисел та чому 0.1 + 0.2 не дорівнює 0.3 у JavaScript.
На відміну від рядків і масивів, Math не є типом даних — це готовий об'єкт-набір методів і констант, доступний глобально, без потреби щось імпортувати чи створювати:
Math.round(4.5); // 5 — округлення до найближчого цілого
Math.floor(4.9); // 4 — завжди вниз
Math.ceil(4.1); // 5 — завжди вгору
Math.trunc(4.9); // 4 — просто відкидає дробову частину (не плутати з floor для від'ємних чисел)
Math.abs(-7); // 7 — модуль числа
Math.max(3, 7, 2); // 7
Math.min(3, 7, 2); // 2
Math.pow(2, 10); // 1024 — те саме, що 2 ** 10
Math.sqrt(64); // 8Math.floor і Math.trunc дають однаковий результат для додатних чисел, але різний для від'ємних: Math.floor(-4.5) дорівнює -5 (завжди вниз), а Math.trunc(-4.5) дорівнює -4 (просто відкидає дробову частину).
Math.random() повертає дробове число від 0 (включно) до 1 (не включно) — для випадкового цілого в діапазоні потрібна невелика формула:
function randomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
randomInt(1, 6); // випадкове число від 1 до 6, як кубикconst price = 19.999;
price.toFixed(2); // "19.99" — рядок, не число! зверніть увагу на лапкиtoFixed повертає рядок, а не число — якщо результат потрібен для подальших обчислень, а не лише для показу користувачу, знадобиться Number(price.toFixed(2)).
Один із найвідоміших «дивних» результатів у JavaScript (і практично в будь-якій мові, що використовує стандарт IEEE 754 для чисел із рухомою комою):
0.1 + 0.2; // 0.30000000000000004, НЕ 0.3Причина не в помилці JavaScript, а в тому, як комп'ютери зберігають дробові числа у двійковій системі: так само, як 1/3 не можна точно записати скінченним десятковим дробом, 0.1 не можна точно записати скінченним двійковим дробом — лишається крихітна похибка округлення.
Для порівняння дробових чисел на «практичну рівність» перевіряйте різницю з малим допуском замість ===: Math.abs(a - b) < 0.0001. Для грошових розрахунків найнадійніше рахувати в цілих одиницях (копійках/центах), а не в дробових гривнях/доларах — тоді проблема зникає повністю.
На відміну від Number() (модуль «JavaScript під капотом» не розглядав це, але Number() вимагає, щоб увесь рядок був коректним числом), parseInt/parseFloat читають число з початку рядка, ігноруючи все, що йде після:
Number("42px"); // NaN — весь рядок має бути числом
parseInt("42px"); // 42 — читає, доки символи схожі на число
parseFloat("3.14m"); // 3.14Завжди передавайте другим аргументом систему числення (radix) для parseInt: parseInt("08", 10). Без явного 10 деякі рядки (наприклад, з провідним нулем у старих рушіях) могли інтерпретуватись у восьмирічній системі — сучасні рушії вже за замовчуванням використовують десяткову, але явний radix лишається доброю звичкою й документує намір коду.
function roundToCents(amount) {
return Math.round(amount * 100) / 100;
}
roundToCents(19.9949); // 19.99
roundToCents(0.1 + 0.2); // 0.3 — «лікує» похибку рухомої коми для показуПорівняння дробових чисел через === без урахування похибки рухомої коми.
Використання результату toFixed() як числа напряму (наприклад, у подальшому додаванні) без обгортання в Number().
Виклик parseInt без radix там, де формат рядка непередбачуваний.
Math надає готові методи для округлення, випадкових чисел і базової арифметики без потреби писати їх самостійно. toFixed форматує число для показу, повертаючи рядок. Похибка рухомої коми (0.1 + 0.2 !== 0.3) — властивість того, як будь-яка мова зберігає дробові числа у двійковому форматі, а не помилка JavaScript; для грошових розрахунків найнадійніше працювати в цілих одиницях.
Спробуйте самостійно
Напишіть функцію randomHexColor(), що повертає випадковий колір у форматі "#a3f29c" — підказка: Math.random() для генерації числа, toString(16) для переведення числа в шістнадцяткову систему, padStart з попереднього уроку для гарантії двох цифр на кожен канал.