diff --git a/1-js/05-data-types/02-number/article.md b/1-js/05-data-types/02-number/article.md index ed7f9a8be..4a06296fe 100644 --- a/1-js/05-data-types/02-number/article.md +++ b/1-js/05-data-types/02-number/article.md @@ -31,7 +31,7 @@ let billion = 1_000_000_000; ```js run let billion = 1e9; // 1 мільярд, буквально: 1 та 9 нулів -alert( 7.3e9 ); // 7.3 мільярдів (таке ж саме що 7300000000 чи 7_300_000_000) +alert( 7.3e9 ); // 7.3 мільярдів (те ж саме, що й 7300000000 чи 7_300_000_000) ``` Іншими словами, `"e"` помножує число на `1` із заданим числом нулів. @@ -89,18 +89,18 @@ let b = 0o377; // вісімкова форма 255 alert( a == b ); // true, те саме число 255 з обох сторін ``` -Є лише 3 системи числення з такою підтримкою. Для інших систем числення ми повинні використовувати функцію `parseInt` (яку ми побачимо далі в цьому розділі). +Таким способом підтримуються лише 3 системи числення. Для інших систем числення ми повинні використовувати функцію `parseInt` (яку ми побачимо далі в цьому розділі). ## toString(base) -Метод `num.toString(base)` повертає рядкове представлення `num` в системі числення із заданим `base`. +Метод `num.toString(base)` повертає `num` у вигляді рядка, в якому вказане це ж число, але в системі числення із заданим `base`. Наприклад: ```js run let num = 255; -alert( num.toString(16) ); // ff -alert( num.toString(2) ); // 11111111 +alert( num.toString(16) ); // "ff" +alert( num.toString(2) ); // "11111111" ``` `base` може бути від `2` до `36`. За замовчуванням це `10`. @@ -108,11 +108,11 @@ alert( num.toString(2) ); // 11111111 Загальні випадки використання для цього є: - **base=16** використовується для шістнадцяткових кольорів, кодування символів тощо, цифри можуть бути `0..9` або `A..F`. -- **base=2** в основному для налагодження бітових операцій, цифри можуть бути `0` або `1`. -- **base=36** є максимальним, цифри можуть бути `0..9` або `A..Z`. Весь латинський алфавіт використовується для позначення числа. Комічно, але користь від системи для найбільших чисел полягає у перетворенні довгого числового ідентифікатора у щось коротше, наприклад, для генерації короткого URL. Для цього достатньо представити його в системі числення з базою `36`: +- **base=2** використовується в основному для налагодження бітових операцій, цифри можуть бути `0` або `1`. +- **base=36** є максимальною, цифри можуть бути `0..9` або `A..Z`. Для позначення такого числа в якості цифер використовується увесь латинський алфавіт. Кумедно, але переведення числа в таку систему числення буває корисним коли ми маємо дуже довгий числовий ідентифікатор і хочемо перетворити його на щось коротше, бо хочемо зробити URL коротшим. Для цього достатньо представити його в системі числення з базою `36`: ```js run - alert( 123456..toString(36) ); // 2n9c + alert( 123456..toString(36) ); // "2n9c" ``` ```warn header="Дві крапки для виклику методу" @@ -181,7 +181,7 @@ alert( num.toString(2) ); // 11111111 alert( num.toFixed(1) ); // "12.4" ``` - Зверніть увагу, що результат `toFixed` -- це рядок. Якщо десяткова частина коротша, ніж потрібно, нулі додаються в кінці: + Зверніть увагу, що результат `toFixed` -- це рядок. І в кінці можуть додаватись нулі якщо десяткова частина коротша, ніж потрібно: ```js run let num = 12.34; @@ -192,7 +192,7 @@ alert( num.toString(2) ); // 11111111 ## Неточні розрахунки -Із середини, число представлено у 64-бітному форматі [IEEE-754](https://en.wikipedia.org/wiki/IEEE_754), тому для його зберігання треба саме 64 біти: 52 з них використовуються для зберігання цифр, 11 -- відповідають за позицію десяткової крапки (для цілих чисел вони дорівнюють нулю), а 1 біт -- для знака. +Із середини, число представлено у 64-бітному форматі [IEEE-754](https://en.wikipedia.org/wiki/IEEE_754), тому для його зберігання треба саме 64 біти: 52 з них використовуються для зберігання цифр, 11 -- відповідають за позицію десяткової крапки (для цілих чисел вони дорівнюють нулю), а 1 біт -- для полярності (тобто інформації чи йде перед числом знак мінус, чи ні). Якщо число занадто велике, та переповнює 64-біти, воно буде перетворене на спеціальне числове значення `Infinity`(Нескінченність): @@ -220,7 +220,7 @@ alert( 0.1 + 0.2 ); // 0.30000000000000004 Але чому так відбувається? -Число зберігається в пам’яті у його двійковій формі, послідовність бітів - одиниць і нулів. Але дроби на кшталт `0.1`, `0.2`, які виглядають просто в десятковій системі числення, насправді є нескінченними дробами у своїй двійковій формі. +Число зберігається в пам’яті у його двійковій формі, як послідовність бітів - одиниць і нулів. Але дроби на кшталт `0.1`, `0.2`, які виглядають просто в десятковій системі числення, насправді є нескінченними дробами у своїй двійковій формі. Іншими словами, що таке `0.1`? Це одиниця розділена на десять `1/10` -- одна десята. У десятковій системі такі числа досить легко представити, але якщо порівняти його з однією третиною: `1/3`, то ми стикаємось з нескінченним дробом `0.33333(3)`. @@ -252,7 +252,7 @@ let sum = 0.1 + 0.2; alert( sum.toFixed(2) ); // "0.30" ``` -Зауважте, що `toFixed` завжди повертає рядок, щоб число гарантовано мало дві цифри після десяткової крапки. Це насправді зручно, якщо у нас є електронні покупки та нам потрібно показати `$0.30`. В інших випадках ми можемо використовувати одинарний плюс, щоб для приведення його до числа: +Зауважте, що `toFixed` завжди повертає рядок, щоб число гарантовано мало дві цифри після десяткової крапки. Та й взагалі це зручно, якщо у нас є електронні покупки та нам потрібно показати `$0.30`. В інших випадках ми можемо використовувати одинарний плюс, якщо хочемо результат `toFixed` конвертувати в число: ```js run let sum = 0.1 + 0.2; @@ -268,7 +268,7 @@ alert( (0.28 * 100 + 0.14 * 100) / 100); // 0.4200000000000001 Отже, підхід множення/ділення зменшує помилку, але не видаляє її повністю. -Іноді можна спробувати уникнути проблем з дробами. Якщо ми маємо справу з магазином, то можемо зберігати ціни в центах замість доларів. Але що робити, якщо ми застосуємо знижку в розмірі 30%? На практиці повністю уникнути дробів вдається досить рідко. Просто округліть їх, щоб вирізати "хвости", коли це потрібно. +Іноді можна спробувати уникнути проблем з дробами. Якщо ми маємо справу з магазином, то можемо зберігати ціни в центах замість доларів. Але що робити, якщо ми застосуємо знижку в розмірі 30%? На практиці повністю уникнути дробів вдається досить рідко. Тому просто округляйте їх, щоб відрізати "хвости", коли це потрібно. ````smart header="Цікавий факт" Спробуйте запустити: @@ -286,7 +286,7 @@ JavaScript не викликає помилку в таких випадках. ```smart header="Два нулі" Ще одним кумедним наслідком внутрішньої реалізації чисел є наявність двох нулів: `0` і `-0`. -Це тому, що знак представлений одним бітом, тому його можна встановити або не встановити для будь-якого числа, включаючи нуль. +Це тому, що в усіх чисел є один біт для знака. А тому знак можна встановити або не встановити для будь-якого числа, навіть для нуля. У більшості випадків відмінність непомітна, оскільки оператори підходять до них як до однакових. ``` @@ -308,13 +308,13 @@ JavaScript не викликає помилку в таких випадках. alert( isNaN("str") ); // true ``` - Але чи потрібна нам ця функція? Чи не можемо ми просто використати порівняння `=== NaN`? Вибачте, але відповідь -- ні. Значення `NaN` унікальне тим, що воно нічому не дорівнює, включаючи себе: + Але чи потрібна нам ця функція? Чи не можемо ми просто використати порівняння `=== NaN`? Вибачте, але відповідь -- ні. Значення `NaN` унікальне тим, що воно нічому не дорівнює, навіть самому собі: ```js run alert( NaN === NaN ); // false ``` -- `isFinite(value)` перетворює свій аргумент в число і повертає `true`, якщо це звичайне число, та `false`, якщо `NaN/Infinity/-Infinity`: +- `isFinite(value)` перетворює свій аргумент в число і повертає `true`, якщо це звичайне число. Або `false`, якщо `NaN/Infinity/-Infinity`: ```js run alert( isFinite("15") ); // true @@ -328,7 +328,7 @@ JavaScript не викликає помилку в таких випадках. ```js run let num = +prompt("Enter a number", ''); -// буде істинним, якщо ви не введете Infinity, -Infinity чи не число +// буде true, якщо ви не введете Infinity, -Infinity чи NaN alert( isFinite(num) ); ``` @@ -364,12 +364,12 @@ alert( isFinite(num) ); ```` ```smart header="Порівняння з `Object.is`" -Існує спеціальний вбудований метод `Object.is`, який порівнює значення як `===`, але є більш надійним для двох виключень: +Існує спеціальний вбудований метод `Object.is`, який порівнює значення як `===`, але є більш надійним для двох виняткових випадків: 1. Працює з `NaN`: `Object.is(NaN, NaN) === true`, і це добре. 2. Значення `0` і` -0` різні: `Object.is(0, -0) === false`, технічно це правда, оскільки внутрішньо число має біт знаків, який може бути різним, навіть якщо всі інші біти -- нулі. -У всіх інших випадках `Object.is(a, b)` те саме, що `a === b`. +У всіх інших випадках `Object.is(a, b)` поверне те саме, що й `a === b`. Ми згадуємо тут `Object.is`, оскільки він часто використовується в специфікації JavaScript. Коли для внутрішнього алгоритму потрібно порівняти два значення, щоб вони були абсолютно однаковими, він використовує `Object.is` (ще його називають [SameValue](https://tc39.github.io/ecma262/#sec-samevalue)). ``` @@ -389,7 +389,7 @@ alert( +"100px" ); // NaN Ось для чого призначені `parseInt` та `parseFloat`. -Вони "читають" число з рядка, до поки можуть, у разі помилки зчитане число повертається. Функція `parseInt` повертає ціле число, тоді як `parseFloat` повертає число з плаваючою крапкою: +Вони допоки можуть -- доти "читають" число з рядка. І у разі помилки зчитане число повертається. Функція `parseInt` повертає ціле число, тоді як `parseFloat` повертає число з плаваючою крапкою: ```js run alert( parseInt('100px') ); // 100 @@ -450,9 +450,9 @@ JavaScript має вбудований [Math](https://developer.mozilla.org/uk/d ## Підсумки -Щоб записати числа з багатьма нулями: +Для написання числа з багатьма нулями: -- Додайте `"e"` з числом нулів до числа. Як і: `123e6` те саме, що `123` з 6 нулями `123000000`. +- Додайте `"e"` з кількістю нулів до числа. Наприклад `123e6` -- це те саме, що `123` з 6 нулями `123000000`. - Від’ємне число після `"е"` призводить до ділення числа на 1 із заданими нулями. Наприклад `123e-6` означає `0.000123` (`123` мільйони). Для різних систем числення: @@ -463,10 +463,10 @@ JavaScript має вбудований [Math](https://developer.mozilla.org/uk/d Для регулярних тестів чисел: -- `isNaN(value)` перетворює свій аргумент на число, а потім перевіряє його на `NaN` -- `Number.isNaN(value)` перевіряє, чи належить його аргумент до типу `number`, і якщо так, перевіряє його на `NaN` -- `isFinite(value)` перетворює свій аргумент на число, а потім перевіряє, чи не є `NaN/Infinity/-Infinity` -- `Number.isFinite(value)` перевіряє, чи належить його аргумент до типу `number`, і якщо так, перевіряє, чи не є `NaN/Infinity/-Infinity` +- `isNaN(value)` перетворює свій аргумент на число, а потім перевіряє чи він `NaN` +- `Number.isNaN(value)` перевіряє, чи належить його аргумент до типу `number`, і якщо так, перевіряє чи він `NaN` +- `isFinite(value)` перетворює свій аргумент на число, а потім перевіряє, чи не є він `NaN/Infinity/-Infinity` +- `Number.isFinite(value)` перевіряє, чи належить його аргумент до типу `number`, і якщо так, перевіряє, чи не є він `NaN/Infinity/-Infinity` Для перетворення значень на зразок `12pt` та `100px` у число: