Математика в JavaScript


Введення
Наявність чисел і числових даних дозволяє вам якимось чином працювати з мовою. Але крім роботи з арифметичними операторами в JavaScript, математичні конструкції можуть бути складним завданням для новачків. З цієї причини, потрібно концентруватися не на синтаксисі, а на загальних математичних функціях, цей список починається з таких речей як сортування, округлення і генерація випадкових значень, цього достатньо, перш ніж заглиблюватися в деталі. Щоб працювати з математикою в JavaScript вам достатньо мати поняття про такі речі як функція, оператор і оператор.

Від перекладача
Всім привіт, з вами Максим Іванов, і сьогодні я вирішив, що ми не будемо говорити про модні і корисних штуках типу ReactJS, Angular, TypeScript та інших. Сьогодні ми приділимо увагу математики в JavaScript. Якщо вам подобається математика, ви можете займатися їй весь вільний час, але якщо вашою метою є не наукові дослідження, а робота програмістом, математика навряд чи стане кращим об'єктом для вивчення.

  1. Робота з випадковими числами

  2. Округлення

  3. Сортування


  4. Робота зі степеневими функціями

  5. Математичні константи

  6. Math.abs, parseInt, parseFloat

Робота з випадковими числами
Випадкові числа часто потрібні в JavaScript, наприклад, для малювання зірок, розкиданих по нічному небу. Але є багато різних видів випадковостей, і в залежності від логіки і потреб вашого застосування вам може знадобитися один з них.

Основний випадок
Найпростіша форма випадковості — це функція Math.random(), вбудована в JavaScript.

> Math.random()
0.19401081069372594

Math.random() завжди повертає число з плаваючою крапкою між 0 і 1. З технічної точки зору число, що повертається за допомогою Math.random() може бути 0, але ніколи не буде дорівнює 1.

Якщо ви часто використовуйте Math.random(), використовуйте свою власну функцію в сценаріях:

function getRandom() {
return Math.random();
}

Проблема, звичайно, в тому, що дана функція завжди буде створювати випадкове число в межах вельми обмеженого діапазону, далі ми постараємося розглянути деякі рекомендації призначені для вирішення цієї проблеми.

Випадкове число в інтервалі [min, max)
Розширення такої функціональності вимагає трохи математики:

Випадкове число з плаваючою крапкою:

function getRandomFloat(min, max) {
return Math.random() * (max - min) + min;
}

getRandomFloat(11, 101)
> 75.31898734299466

Ціле випадкове число:

function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}

getRandomInt(10, 20)
> 12

Випадкове число в інтервалі [min, max]
function getRandomInRange(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}

getRandomInRange(1, 10)
> 7

Булівські випадкові величини (true/false)
Якщо ви хочете просту випадковість 0 або 1, що представляє підкидання монети:

function coinToss() {
return Math.floor(Math.random() * 2);
}

coinToss();
> 0

Якщо вам потрібно отримати true або false:

function coinToss() {
return (Math.floor(Math.random() * 2) === 0);
}

coinToss();
> true

Або ж:

function coinToss() {
return Math.random()<.5;
}

coinToss();
> true

Якщо ви хочете зв'язати конкретні слова зі сторонами монети (так / ні, верх / низ і т. д.):

function coinFlip() {
return (Math.floor(Math.random() * 2) === 0) ? "up" : "down";
}

coinToss();
> up

Випадкові величини з винятками
Для обмеженого діапазону цілих чисел необхідно створити масив чисел, які ви хотіли б отримати і надалі вибрати випадковим чином з цього масиву:

let numPool = [ 1, 3, 5, 7, 9, 10 ],
rand = numPool[Math.floor(Math.random() * numPool.length)];

Можна також використовувати масив чисел, які ви хочете виключити, і приготувати порожній масив, в якому буде міститися результат фільтрації з першого масиву у другій:

let numPool = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
let excludePool = [ 3, 4 ];
let filteredPool = [];

Потім у циклі проганяємо масив numPool, якщо число, що випало існує і знаходиться в масиві excludePool, поміщаємо результат в filteredPool:

for (let i = 0; i < numPool.length; i++) {
if (excludePool.indexOf(numPool[i]) === -1) {
filteredPool.push(numPool[i]);
}
}

І, нарешті, отримуємо випадкові числа з масиву filteredPool:

let rand = filteredPool[Math.floor(Math.random() * filteredPool.length)];

Випадкові величини без повторень
Для невеликого набору чисел необхідно створити масив заповнений елементами, далі перетасуйте їх у випадковому порядку, помістіть результат в новий масив, а потім витягайте по одному:

let numPool = [ 13, 21, 36, 14, 27, 10 ];

function shuffle(numPool) {

for(
let j, x, i = numPool.length; i; 
j = parseInt(Math.random() * i), 
x = numPool[--i], 
numPool[i] = numPool[j], 
numPool[j] = x
);

return numPool;
};

let randomResult = shuffle(numPool);
while( randomResult.length > 0 ) {
console.log( randomResult.pop() );
}

Для отримання більш широкого діапазону чисел, створити і заповнити масив випадковими числами, виключаючи будь-які, які були раніше згенеровані:

let numReserve = []
while (numReserve.length < 12) {
let randomNumber = Math.ceil(Math.random() * 1000);
let found = false;
for (let i = 0; i < numReserve.length; i++) {
if (numReserve[i] === randomNumber){ 
found = true;
break;
}
}
if (!found) { numReserve[numReserve.length]=randomNumber; }
}

У наведеному вище коді numReserve заповнюється 12ю випадковими числами від 0 до 1000.

Криптографічні випадкові величини
На жаль, жоден з вище методів не створює число з достатньою хаотичністю для криптографічно захищених функцій (Math.random() не є достатньою функцією, яка генерує випадкові числа). Тому, ми можемо використовувати Web Cryptography API шляхом створення typedArray:

let cryptoStor = new Uint16Array(8);

У цьому випадку ми створюємо масив з вісьмома різними слотами, кожен з яких містить беззнакове 16-розрядне ціле число. Існують і інші варіанти Int8Array, Uint8Array, int16Array, Int32Array і Uint32Array.

Потім, необхідно заповнити масив випадковими числами певного типу:

window.crypto.getRandomValues(cryptoStor);
> [43484, 57947, 46691, 49849, 24272, 11827, 28203, 17423]

До всього іншого, Web Cryptography API має хорошу підтримку сучасних браузерах.

До прочитання:
1. Випадкове просте число
2. Генерація випадкових цілих чисел в JavaScript в певному діапазоні
3. Введення в криптографію
4. Криптографічно стійкого генератор псевдовипадкових чисел
5. Генератор псевдовипадкових чисел

Округлення
Дуже часто обчислення JavaScript дають не зовсім ті результати, які ми хочемо. Зрозуміло, ми можемо робити з числами що завгодно — округляти в більшу або меншу сторону, встановлювати діапазони, відсікати непотрібні числа до певної кількості знаків після коми, все залежить від того, що ви хочете зробити у подальшому з цим числом.

Навіщо необхідно округлення?
Одним із цікавих аспектів JavaScript є те, що він насправді не зберігає цілі числа, ми відразу ж працюємо з числами з плаваючою точкою. Це, в поєднанні з тим фактом, що багато дробові значення не можуть бути виражені кінцевим числом знаків після коми, у JavaScript ми можемо отримати такі результати:

0.1 * 0.2;
> 0.020000000000000004

0.3 - 0.1
> 0.19999999999999998

Для практичних цілей ця неточність не має ніякого значення, в нашому випадку ми говоримо про помилку квинтиллионных частках, однак, когось це може розчарувати. Ми можемо отримати дещо дивний результат і при роботі з числами, які являють собою значення валют, відсотків або розмірів файлу. Для того, щоб виправити ці помилки, нам якраз і потрібно вміти округляти результати, при цьому достатньо встановити десяткову точність.

Округлення чисел має практичне застосування, ми можемо маніпулювати числом в деякому діапазоні, наприклад, хочемо округлити до найближчого цілого числа, а не працювати тільки з десятковою частиною.

Округлення десяткових чисел
Для того, щоб відсікти десяткове число, використовуйте toFixed або метод toPrecision. Обидва вони приймають єдиний аргумент, який визначає, відповідно, скільки значущих цифр (тобто загальна кількість цифр, використовуваних у числі) або знаків після коми (кількість після десяткової крапки) повинен включати в себе результат:

  1. Якщо аргумент не визначений для toFixed(), то за замовчуванням він дорівнює нулю, що означає 0 знаків після коми, аргумент має максимальне значення, яке дорівнює 20.
  2. Якщо аргумент не задано для toPrecision, число залишається недоторканим
let randNum = 6.25;
randNum.toFixed();
> "6"

Math.PI.toPrecision(1);
> "3"

randNum = 87.335;
randNum.toFixed(2);
> "87.33"

randNum = 87.337;
randNum.toPrecision(3);
> "87.3"

Обидва методу toFixed() і toPrecision() повертає рядкове представлення результату, а не кількість. Це означає, що при підсумовуванні округленого значення з randNum буде проведена конкатенація рядків, а не сума чисел:

let randNum = 6.25;
let rounded = randNum.toFixed(); // "6"
console.log(randNum + rounded);
> "6.256"

Якщо ви хочете, щоб результат мав числовий тип даних, то вам необхідно буде застосувати parseFloat:

let randNum = 6.25;
let rounded = parseFloat(randNum.toFixed(1));
console.log(rounded);
> 6.3

Зверніть увагу, що значення 5 округлені, за винятком рідкісних випадків.

Методи toFixed() і toPrecision() є корисними, бо вони можуть не тільки відсікати дробову частину, але й доповнювати знаки після коми, що зручно при роботі з валютою:

let wholeNum = 1
let dollarsCents = wholeNum.toFixed(2);
console.log(dollarsCents);
> "1.00"

Коштувати зверніть увагу, що toPrecision буде давати результат в експоненційної запису, якщо число цілих чисел більше, ніж сам сама точність:

let num = 123.435
num.toPrecision(2);
> "1.2 e+2"

Як уникнути помилок округлення з десятковими числами
У деяких випадках, toFixed і toPrecision округляє значення 5 в меншу сторону, а у велику:

let numTest = 1.005;
numTest.toFixed(2);
> "1.00"

Результат розрахунку вище повинен був бути 1.01, а не 1. Якщо ви хочете уникнути подібної помилки, ми можемо використовувати рішення, запропоноване Jack L Moore, яке використовує експоненціальні числа для розрахунку:

function round(value, decimals) {
return Number(Math.round(value+'e'+decimals)+'e'+decimals);
}

Тепер:

round(1.005,2);
> 1.01

Якщо ви хочете більш надійне рішення, ніж рішення показане вище, ви можете перейти на MDN.

Машинне епсилон округлення
Альтернативний метод округлення десяткових чисел був введений в ES6. Машинне епсилон округлення забезпечує розумна межа похибки при порівнянні двох чисел з плаваючою точкою. Без округлення, порівняння можуть дати результати, подібні наступним:

0.1 + 0.2 === 0.3
> false

Ми використовуємо Math.EPSILON в нашій функції для отримання коректного порівняння:

function epsEqu(x, y) {
return Math.abs(x - y) < Number.EPSILON * Math.max(Math.abs(x), Math.abs(y));
}

Функція приймає два аргументи: перший — поточний розрахунок, другий — очікуваний результат. Вона повертає порівняння двох:

epsEqu(0.1 + 0.2, 0.3)
> true

Всі сучасні браузери вже підтримують ES6 математичні функції, але якщо ви хочете отримати підтримку в таких браузерах, як IE 11, використовуйте polyfills.

Відсікання дробової частини
Всі методи, представлені вище вміють округляти до десяткових чисел. Для того, щоб відсікти число до двох знаків після коми, необхідно спочатку помножити його на 100, а потім отриманий результат розділити на 100:

function truncated(num) {
return Math.trunc(num * 100) / 100;
}

truncated(3.1416)
> 3.14

Якщо ви хочете пристосувати метод під будь-яку кількість знаків після коми, ви можете скористатися подвійним побітовим запереченням:

function truncated(num, після коми) { 
let numPowerConverter = Math.pow(10, після коми); 
return ~~(num * numPowerConverter)/numPowerConverter;
}

Тепер:

let randInt = 35.874993;
truncated(randInt,3);
> 35.874

Округлення до найближчого числа
Для того, щоб округлити десяткове число до найближчого числа в більшу чи в меншу сторону, залежно від того, до чого ми ближче всього, використовуйте Math.round():

Math.round(4.3)
> 4

Math.round(4.5)
> 5

Зверніть увагу, що «половина значення», 0.5 округлюється в більшу сторону за правилами математики.

Округлення до меншого до найближчого цілого числа
Якщо ви хочете завжди округляти в меншу сторону, використовуйте Math.floor:

Math.floor(42.23);
> 42

Math.floor(36.93);
> 36

Зверніть увагу, що округлення в меншу сторону працює для всіх чисел, в тому числі і для негативних. Уявіть хмарочос з нескінченною кількістю поверхів, у тому числі з поверхами нижнього рівня (представляє від'ємні числа). Якщо ви знаходитесь в ліфті на нижнім рівнем між 2 і 3 (що являє собою значення -2.5), Math.floor доставить вас до -3:

Math.floor(-2.5);
> -3

Але якщо ви хочете уникнути подібної ситуації, використовуйте Math.truncпідтримуваний у всіх сучасних браузерах (крім IE / Edge):

Math.trunc(-41.43);
> -41

На MDN ви знайдете polyfill, який забезпечить підтримку Math.trunc в браузерах і IE / Edge.

Округлення до більшого до найближчого цілого числа
З іншого боку, якщо вам потрібно завжди округляти в більшу сторону, використовуйте Math.ceil. Знову ж, згадуємо нескінченний ліфт: Math.ceil завжди буде йти «угору», незалежно від того, чи є число від'ємне чи ні:

Math.ceil(42.23);
> 43

Math.ceil(36.93);
> 37

Math.ceil(-36.93);
> -36

Округлення до більшого/меншого необхідного числа
Якщо ми хочемо, щоб округлити до найближчого числа, кратного 5, найпростіший спосіб створити функцію, яка ділить число на 5, округлює його, а потім множить його на ту ж суму:

function roundTo5(num) {
return Math.round(num/5)*5;
}

Тепер:

roundTo5(11);
> 10

Якщо ви хочете округляти до кратних своїм значенням, ми використовувати більш загальну функцію, передаючи в неї початкове значення і кратне:

function roundToMultiple(num, multiple) {
return Math.round(num/multiple)*multiple;
}

Тепер:

let initialNumber = 11;
let multiple = 10;
roundToMultiple(initialNumber, multiple);
> 10;

Фіксування числа в діапазоні
Є багато випадків, коли ми хочемо отримати значення х, що лежить в межах діапазону. Наприклад, нам може знадобитися значення від 1 до 100, але при цьому ми отримали значення 123. Для того, щоб виправити це, ми можемо використовувати мінімальне (повертає найменше з набору чисел) і максимальне (повертає найбільше з будь-якого безлічі чисел). У нашому прикладі, діапазон від 1 до 100:

let lowBound = 1;
let highBound = 100;
let numInput = 123;
let clamped = Math.max(lowBound, Math.min(numInput, highBound));
console.log(clamped);
> 100;

Знову ж таки, ми можемо переиспользовать операцію і обернути все це в функцію, скористаємося рішенням запропоноване Daniel X. Moore:

Number.prototype.clamp = function(min, max) {
return Math.min(Math.max(this, min), max);
};

Тепер:

numInput.clamp(lowBound, highBound);
> 100;

гаусівських розподілу округлення
Гаусівських розподілу округлення, також відоме як банківська округленням, полягає в тому, що округлення для цього випадку відбувається до найближчого парним. Цей метод округлення працює без статистичної похибки. Краще рішення було запропоновано Tim Down:

function gaussRound(num, після коми) {
let d = після коми || 0,
m = Math.pow(10, d),
n = +(d ? num * m : num).toFixed(8),
i = Math.floor(n), f = n - i,
e = 1e-8,
r = (f > 0.5 - e && f < 0.5 + e) ?
((i % 2 == 0) ? i : i + 1) : Math.round(n);
return d ? r / m : r;
}

Тепер:

gaussRound(2.5)
> 2

gaussRound(3.5)
> 4

gaussRound(2.57,1)
> 2.6

Десятковий знак в CSS:

Так як JavaScript часто використовується для створення позиційного перетворення елементів HTML, ви можете задатися питанням, що станеться, якщо ми згенеруємо десяткові значення для наших елементів:

#box { width: 63.667731993 px; }

Гарна новина полягає в тому, що сучасні браузери будуть враховувати десяткові значення в блочної моделі, в тому числі в процентних або піксельних одиницях виміру.

До прочитання:
1. Що кожний учений повинен знати про арифметиці при роботі з плаваючою комою
2. Швидка JavaScript-бібліотека, що працює з десяткової арифметикою довільної точності
3. Розширений тип Decimal довільної точності для JavaScript
4. JavaScript-бібліотека довільної точності для десятковій і довільної арифметики
5. Що повинен знати кожен JavaScript-розробник про плаваючою комою
6. Чому такі проблеми з плаваючою комою в JS?

Сортування
Дуже часто нам доводиться сортувати елементи, наприклад, у нас є масив ігрових рекордів, при цьому вони повинні бути впорядковані за спаданням рангу гравців. На жаль, стандартний метод sort() має деякі дивовижні обмеження: він добре працює з часто вживаними англійськими словами, але одразу ж ламається при зустрічі з числами, унікальними символами або словами в верхньому регістрі.

Сортування в алфавітному порядку
Здавалося б, сортування масиву за алфавітом повинна бути простим завданням:

let fruit = ["butternut squash", "apricot", "cantaloupe"];
fruit.sort();

> "apricot", "butternut squash", "cantaloupe"]

Тим не менше ми стикаємося з проблемою, як тільки один з елементів знаходиться у верхньому регістрі:

let fruit = ["butternut squash", "apricot", "Cantalope"];
fruit.sort();

> "Cantaloupe", "apricot", "butternut squash"]

Це пов'язано з тим, що, за замовчуванням, сортувальник порівнює перший символ представлений в Unicode. Unicode — це унікальний код для будь-якого символу, незалежно від платформи, незалежно від програми, незалежно від мови. Наприклад, якщо дивитися кодової таблиці символ «a» має значення U+0061 (у шістнадцятковій системі 0x61), в той час як символ «C» має код U+0043 (0x43), який йде раніше в Unicode-таблиці, ніж символ «a».

Щоб відсортувати масив, який може містити змішані регістри перших букв, нам необхідно або перетворити всі елементи тимчасово в нижній регістр, або визначити свій порядок сортування за допомогою методу localeCompare() c деякими аргументами. Як правило, для такого випадку, краще відразу створити функцію для багаторазового використання:

function alphaSort(arr) {
arr.sort(function (a, b) {
return a.localeCompare(b, 'en', {'sensitivity': 'base'});
});
}

let fruit = ["butternut squash", "apricot", "Cantaloupe"];
alphaSort(fruit)

> ["apricot", "butternut squash", "Cantaloupe"]

Якщо ви хочете отримати масив відсортований в зворотному алфавітному порядку, просто поміняйте позиціями а і b у функції:

function alphaSort(arr) {
arr.sort(function (a, b) {
return b.localeCompare(a, 'en', {'sensitivity': 'base'});
});
}

let fruit = ["butternut squash", "apricot", "Cantaloupe"];
alphaSort(fruit)

> ["Cantaloupe", "butternut squash", "apricot"]

Тут варто звернути увагу, що localeCompare використовується з аргументами, ще треба пам'ятати, що він підтримується IE11+, для більш старих версій IE, ми можемо використовувати його без аргументів, і в нижньому регістрі:

function caseSort(arr) {
arr.sort(function (a, b) {
return a.toLowerCase().localeCompare(b.toLowerCase());
});
}

let fruit = ["butternut squash", "apricot", "Cantaloupe"];
caseSort(fruit)

> ["apricot", "butternut squash", "Cantaloupe"]

Числова сортування
Все це не відноситься до того прикладу, про який ми говорили вище про масив ігрових рекордів. З деякими числовими масивами сортування працює просто ідеально, але в якийсь момент результат може бути непередбачуваним:

let highScores = [11, 57, 10, 16, 32, 100];
highScores.sort();

> [10, 100, 11, 16, 32, 57]

Справа в тому, що метод sort() виробляє лексикографічну порівняння: а це означає, що числа будуть перетворені в рядок і порівняння будуть знову проводитися шляхом зіставлення першого символу цього рядка у порядку символів Unicode-таблиці. Тому нам знову необхідно визначити свій порядок сортування:

let highScores = [11, 57, 10, 16, 32, 100];
highScores.sort( function(a,b) { return a - b; } ); 

> [10, 11, 16, 32, 57, 100]

Знову ж таки, для сортування чисел у зворотному порядку, поміняйте позиціями a і b у функції.

Сортування JSON-подібної структури
І нарешті, якщо у нас є JSON-подібна структура даних, представлена як масив ігрових рекордів:

let scores = [
{
"name": "Daniel",
"score": 21768
},
{
"name": "Michael",
"score": 33579
},
{
"name": "Alison",
"score": 38395
}
];

У ES6+, ви можете використовувати стрілочні функції:

scores.sort((a, b) => b.score - a.score));

Для старих браузерів, що мають таку підтримку:

scores.sort(function(a, b) { return a.score - b.score });

Як бачите, сортування JavaScript це досить очевидна річ, я сподіваюся, що ці приклади полегшать як-небудь життя.

До прочитання:
1. Сортировка
2. Алгоритм сортування
3. Бульбашкова сортування і всі-всі-всі
4. Природна сортування рядків JavaScript
5. Витончена сортування в JavaScript
6. Javascript Sort Benchmark
7. Looking for performance? Probably you should NOT use [].sort (V8)

Робота зі степеневими функціями
Зведення в ступінь — операція, спочатку визначається як результат багаторазового множення натурального числа на себе, квадратний корінь з числа a — число, що дає a при зведенні в квадрат. Цими функціями ми могли користуватися постійно в повсякденному житті на уроках математики, зокрема при обчисленні площ, об'ємів або навіть при фізичному моделюванні.

В JavaScript степенева функція представлена як Math.pow(), у новому стандарті ES7 був представлений новий оператор зведення в ступінь — " * * ".

Зведення в ступінь
Для того, щоб звести число n-ую ступінь, використовуйте функцію Math.pow(), де перший аргумент це число, яке буде зведене в ступінь, другий аргумент це показник ступеня:

Math.pow(3,2)
> 9

Така форма запису означає 3 в квадраті, або 3 × 3, що приводить до результату 9. Можна навести ще приклад, звичайно:

Math.pow(5,3);
> 125

Тобто, 5 в кубі, або 5 × 5 × 5, дорівнює 125.

ECMAScript 7 — це наступна версія JavaScript, у принципі, ми можемо використовувати новий запропонований оператор зведення в ступінь — * *, така форма запису може бути більш наочною:

3 ** 2 
> 9

На даний момент підтримка цього оператора досить обмежена, тому його не рекомендується використовувати.

Степенева функція може стати в нагоді в самих різних ситуаціях. Простий приклад, обчислення кількості секунд у годині: Math.pow (60,2).

Квадратний і кубічний корінь
Math.sqrt() і Math.cbrt() протилежні функції Math.pow(). Як ми пам'ятаємо, квадратний корінь з числа a — число, що дає a при зведенні в квадрат.

Math.sqrt(9)
> 3

У теж час кубічний корінь з числа a — число, що дає a при зведенні в куб.

Math.cbrt(125)
> 5

Math.cbrt() був введений в специфікацію JavaScript зовсім недавно, і тому підтримується тільки в сучасних браузерах: Chrome 38+, Firefox і Opera 25+ і Safari 7.1+. Ви помітите, що Internet Explorer відсутній в цьому списку, однак на MDN ви знайдете полифилл.

Приклади
Звичайно, ми можемо використовувати і не цілі значення в одній з цих функцій:

Math.pow(1.25, 2);
> 1.5625

Math.cbrt(56.57)
> 3.8387991760286138

Зверніть увагу, що це цілком собі працює і при використанні негативних значеннях аргументів:

Math.pow(-5,2)
> 25

Math.pow(10,-2)
> 0.01

Тим не менш, для квадратного кореня це не буде працювати:

Math.sqrt(-9)
> NaN

З математичного аналізу ми знаємо, що під уявним числом розуміють квадратні корені з від'ємних чисел. І це може привести нас до ще однієї техніці роботи з комплексними числами, але це вже інша історія.

Ви можете використовувати дробові значення Math.pow(), щоб знайти квадратні і кубічні корені чисел. Квадратний корінь використовує показник 0.5:

Math.pow(5, 0.5); // = Math.sqrt(5) = 5 ** (1/2)
> 2.23606797749979

Однак, з-за примх з плаваючою точкою, ви не можете точно передбачити правильний результат:

Math.pow(2.23606797749979,2)
> 5.000000000000001

В таких ситуаціях, ви вам доведеться вдаватися до відсікання знаків у кількості або округлення до якого-небудь значення.

Деякі, з незрозумілих причин JavaScript плутають функцію Math.pow () Math.exp(), яка є експоненціальною функцією для чисел, в цілому. Примітка: в англійській мові «показник ступеня» перекладається як «exponent», тому це швидше відноситься до англомовним, хоча існують і альтернативні назви показника ступеня, такі як index, power.

До прочитання:
1. Math.pow(num, 2) vs (self = num) * self
2. Арифметичний квадратний корінь з від'ємного числа
3. Приклад розв'язання квадратного рівняння з від'ємним дискриминантом
4. Велика математична бібліотека для JavaScript і Node.js
5. MathML і polyfill

Математичні константи
Робота з математикою в JavaScript полегшується за рахунок ряду вбудованих констант. Ці константи є властивостями об'єкта Math. Варто звернути увагу, що константи пишуться у верхньому регістрі, а не CamelCase нотації.

Math.PI
Число Пі — математична константа, рівна відношенню довжини кола до довжини її діаметру. Стара назва — лудольфово число. Пі — ірраціональне число, тобто його значення не може бути точно виражено у вигляді дробу m/n, де m і n — цілі числа. Отже, його десяткове подання ніколи не закінчується і не є періодичним. На папері популярно використовувати його коротку форму запису — 3.14159.

Ваш браузер не може зберігати нескінченне число, так що JavaScript округлює число Пі до такого значення 3,141592653589793, що більш ніж достатньо для більшості завдань.

Хоча це число найбільш поширене в задачах на знаходження довжини, площі кола, число Пі також використовується ймовірності, статистики, інженерних і природничих науках: це як універсальна константа.

Math.SQRT2
Квадратний корінь з числа 2 — позитивне дійсне число, яке при множенні на себе дає число 2. Геометрично корінь з 2 можна представити як довжину діагоналі квадрата зі стороною 1 (це випливає з теореми Піфагора). Це було перше відоме в історії математики ірраціональне число. JavaScript округлює число до такого значення 1.4142135623730951. (З-за помилок округлення JavaScript: Math.SQRT2 * Math.SQRT2 не дорівнює 2).

Math.SQRT1_2
Квадратний корінь з 0.5 — це одиниця, поділена на корінь квадратний з 2. І знову ж таки, це ірраціональне число.

Найпростішими перетвореннями на папері ми можемо записати так:

√(1/2) = √1 / √2 = 1 / √2 = √2 / 2
Але з-за проблем з плаваючою точкою, ми можемо отримати такий результат:

Math.SQRT1_2 === Math.sqrt(1/2)
> true

Math.sqrt(2) / 2 === Math.sqrt(1/2)
> true

1 / Math.sqrt(2) === Math.sqrt(1/2)
> false

Math.E
Як не дивно, математики константа е завжди записувалася в нижньому регістрі, в JavaScript ж це число використовують у верхньому регістрі. Число e — основа натурального логарифма, математична константа, ірраціональне і трансцендентне число. Іноді число e називають числом Ейлера або числом Непера. JavaScript округлює його як 2,718281828459045. Число e відіграє важливу роль у диференціальному і інтегральному численні, а також в багатьох інших розділах математики.

Math.pow(Math.E,1)
> 2.718281828459045

Math.pow(Math.E,2)
> 7.3890560989306495

Math.pow(Math.E,3)
> 20.085536923187664

Натуральний логарифм
Натуральний логарифм — це логарифм за основою e, де e — ірраціональна константа, рівна приблизно 2,718281828. Натуральний логарифм числа x — це показник ступеня, у яку треба звести число e, щоб отримати x. Math.log(х) — це натуральний з x по підставі e.

Math.log(-1); // NaN out of range
Math.log(0); // -Infinity
Math.log(1); // 0
Math.log(10); // 2.302585092994046

Якщо вам потрібно отримати логарифм з y за основою x:

function getBaseLog(x, y) {
return Math.log(y) / Math.log(x);
}

getBaseLog(1/5, 5) 
> -1

Однак, із-за особливостей округлення чисел з плаваючою точкою, відповідь виходить не завжди точний і тільки близький до правильного значення:

getBaseLog(10, 1000)
> 2.9999999999999996

Math.LN2
Властивість Math.LN2 представляє натуральний логарифм з 2 рівний 0.6931471805599453.

Math.LN10
Властивість Math.LN10 представляє натуральний логарифм з 10 рівний 2.302585092994046

Math.LOG2E
Властивість Math.LOG2E являє двійковий логарифм з e рівний 1.4426950408889634

Math.LOG10E
Властивість Math.LOG10E являє десятковий логарифм з e рівний 0.4342944819032518

До прочитання:
1. Математична константа
2. 10 чисел, на яких тримається світ
3. Математичну константу поклали на музику

Math.abs, parseInt, parseFloat
Робота з числами в JavaScript може бути куди більш складним, ніж здається. Отримані значення не завжди потрапляють всередину очікуваних діапазонів, іноді результат може виявитися зовсім не тим, що ми очікували.

Math.abs()
Метод Math.abs() повертає абсолютне значення числа, що нагадує нам аналогічну математичну функціюмодуля числа a.

let newVal = -57.64;
Math.abs(newVal);

> 57.64

Math.abs(0) завжди повертає нуль, але якщо поставити знак мінус перед функцією -Math.abs(NUM) ми завжди будемо від'ємне значення.

-Math.abs(0);
> -0

parseInt()
Ми знаємо, що JavaScript розуміє, що «15» це рядок, а не число і, наприклад, при розборі CSS-властивостей засобами JavaScript, або отримавши якесь значення з непідготовленого масиву, наші результати можуть бути непередбачуваними. Ми могли отримати на вхід рядок представлену як «17px», і для нас це не є рідкістю. Питання полягає в тому, як перетворити цей рядок у фактичне значення і використовувати його в подальших розрахунках.

Синтаксис: parseInt(string, radix);

Функція parseInt перетворює перший переданий їй аргумент в рядковий тип, інтерпретує його і повертає ціле число або значення NaN. Результат (якщо не NaN) є цілим числом і являє собою перший аргумент (string), що розглядається як число в зазначеній системі числення (radix). Наприклад, підстава 10 вказує на перетворення десяткового числа, 8 — восьмеричного, 16 — шістнадцяткового і так далі. Якщо основа більше 10, то для позначення цифр більше 9 використовуються букви. Наприклад, для шістнадцяткових чисел (підстава 16) використовуються букви від A до F.

Розглянемо приклад роботи з CSS-властивості, де, умовно кажучи, ми можемо отримати таке значення:

let elem = document.body;
let centerPoint = window.getComputedStyle(elem).transformOrigin;
> "454px 2087.19 px"

Ми можемо розділити значення по прогалин:

let centers = centerPoint.split(" ");
> ["454px", "2087.19 px"]

Однак, кожен елемент все ще є рядок, ми можемо позбутися цього застосувавши нашу функцію:

let centerX = parseInt(centers[0], 10);
> 454

let centerY = parseInt(centers[1], 10);
> 2087

Як бачите, другим аргументом ми вказуємо систему числення, в яку буде перетворено число, цей параметр необов'язковий, але його рекомендується використовувати у разі, якщо ви не знаєте який рядок надійде на вхід.

parseFloat()
З прикладу вище, ви напевно помітили, що parseInt відкидає дробову частину. В нашому випадку, parseFloat вміє працювати з числами з плаваючою точкою. Знову ж, це може бути корисним при розборі CSS та інших завданнях, особливо при роботі з плаваючою точкою у відсотках.

Синтаксис: parseFloat(string)

let FP = "33.33333%";
console.log(parseFloat(FP));

> 33.33333

Зверніть увагу, що в синтаксисі parseFloat немає другого аргументу.

Ми розуміємо, що parseInt() і parseFloat() є надзвичайно корисними функціями, важливо враховувати, що і тут не обійтися без помилок, тому необхідно перевіряти діапазон очікуваних значень і в кінцевому рахунку аналізувати результат, щоб гарантувати, що отримані значення вірні.

До прочитання:
1. Різниця між parseInt() і parseFloat()
2. У чому різниця між parseInt() та Number() в JavaScript?
3. JavaScript parseInt, Convert String to Int Performance
4. Benchmark: Number vs. mul vs. parseInt vs. parseFloat

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.