Работа с числами и математическими методами в JavaScript

Подборка самых важных и часто используемых методов работы с числами и математическими функциями в JavaScript с примерами.

Вам будет проще разобраться с этими методами, если вы уже знакомы с типами данных в JavaScript.

Основы работы с числами

Это означает, что все числа в JavaScript имеют плавающую запятую. Пусть вас не обманывает запись var x = 1, на самом деле это float, равный 1.0.

Если вы действительно хотите разобраться в особенностях чисел в JS, загляните сюда:

А в этой статье мы сконцентрируемся на методах работы со значениями типа Number.

Создание чисел

Объявить переменную, содержащую числовое значение, можно с помощью ключевых слов let (если она будет изменяться) или const (если не будет). Перед отрицательными числами ставится -:

const PI = 3.14
const x = 1
const n = -10

Единственный 0 в целой или дробной части числа можно не указывать, но все же стоит это делать для лучшей читаемости кода.

const y = 0.15
const z = .90
const t = 5.

Будьте осторожны с ограничениями по размеру:

const r = 9999999999999999 // 10000000000000000
const l = 999999999999999999999999 // 1e+25
const i = Infinity // Infinity - бесконечность со знаком +

Конвертация в число:

const str = '24.23'
const bin = '110110'
const short = +str // 24.23
const num = Number(str) // 24.23

// второй аргумент – основание системы счисления
const b = Number.parseInt(bin, 2) // 54

Можно работать и в других системах счисления:

const hex = 0xff // 255

const octal = 012 // 10
const betterOctal = 0o23 // 19 - способ работы с восьмеричной системой, введенный в ES6

const binary = 0b1101 // 13

Важные принципы

  • все числа – с плавающей точкой;
  • все числа имеют один тип - "number";
  • как и в других языках, в JS существуют ограничения по максимальному размеру и точности чисел.

Основные методы

Безопасные числа

Скорее всего, вы хотите, чтобы значение числа всегда оставалось тем же самым, что вы ему задали. Но если вы используете в коде, к примеру, число 900719925474099164 оно превратится в 900719925474099200. Дело в том, что оно выходит за пределы так называемого безопасного диапазона.

Узнать эти пределы можно, обратившись к свойствам объекта Number MIN_SAFE_INTEGER и MAX_SAFE_INTEGER. А с помощью функции Number.isSafeInteger можно определить, является ли число безопасным.

// константы минимального и максимального безопасных чисел
Number.MAX_SAFE_INTEGER // 9007199254740991
Number.MIN_SAFE_INTEGER // -9007199254740991

// не путайте их с минимальным и максимальным числом
Number.MAX_VALUE // 1.7976931348623157e+308
Number.MIN_VALUE // 5e-324

// проверка, находится ли число в безопасном диапазоне
Number.isSafeInteger(1.7976931348623157e+308) // false
Number.isSafeInteger(9007199254740991) // true

Целое ли число?

Используйте метод isInteger объекта Number. Если число не имеет десятичной части, он возвращает true. Обратите внимание, что числа с пустой десятичной частью автоматически конвертируются в целые.

Number.isInteger(5) // true
Number.isInteger(5 / 2) // false
Number.isInteger(5.00) // true

Есть более короткий, но менее читаемый способ проверить, целое ли число:

5 % 1 === 0 // true
5.5 % 1 === 0 // false

Изменение количества знаков после запятой

Используйте метод Number.toFixed, который принимает количество знаков десятичной части, а возвращает строковое представление числа в нужном формате.

const a = 5.6710142
const b = 0.993

a.toFixed(2) // '5.67'
a.toFixed(1) // '5.7'

b.toFixed() // '1'
b.toFixed(20) // '0.99299999999999999378'
b.toFixed(30) // некоторые браузеры не поддерживают более 20 символов

Также можно воспользоваться методом Number.toPrecision, которому нужно передать количество значащих цифр числа. На выходе также получается строка:

const a = 5.6710142
const b = 0.993

a.toPrecision(2) // '5.7'
a.toPrecision(1) // '6'

b.toPrecision() // 0.993
b.toPrecision(20) // 0.99299999999999999378

Преобразование в экспоненциальную форму

Экспоненциальная форма известна также известна как научная нотация. Для преобразования существует специальный метод toExponential. Его единственный необязательный параметр – количество цифр после запятой.

const x = 25893210
const y = 33.1894
const z = 10000000

const p = x.toExponential() // '2.589321e+7'

y.toExponential() // '3.31894e+1'
z.toExponential() // '1e+7'
z.toExponential(2) // '1.00e+7'

// обратное преобразование

console.log(p) // '2.589321e+7'

Number(p) // 25893210

parseFloat(p) // 25893210

Глобальные функции для работы с числами и методы Number

Вы, возможно, знаете, что существуют глобальные функции вроде parseInt, но только что мы использовали Number.parseInt().

Дело в том, что последний стандарт JavaScript пытается модуляризировать глобальные сущности и обновляет некоторые существующие модули. Например, метод isNaN отличается от нового метода Number.isNaN.

Работа с большими числами

Тип BigInt на данный момент находится в статусе предложения и недоступен в ряде браузеров. Большие числа создаются путем добавления n в конец числа или с помощью конструктора.

const large = 9007199254740991n
const constructed = BigInt(9007199254740991) // 9007199254740991n
const fromString = BigInt('9007199254740991') // 9007199254740991n
const safe = BigInt(Number.MAX_SAFE_INTEGER) // 9007199254740991n

safe + 3n // 9007199254740994n
large + safe // 18014398509481982n

Пока нет полной поддержки BigInt, вы можете использовать библиотеку bignumber.js.

Преобразование в другую систему счисления

Перевести число из десятичной системы в другую можно с помощью метода toString, указав желаемое основание системы (от 2 до 36). Для обратного преобразования используйте метод parseInt:

const num = 3241
const bin = num.toString(2) // '110010101001'

num.toString(8) // '6251'
num.toString(16) // 'ca9'
num.toString(10) // '3241'

Number.parseInt(bin, 2) // 3241

Методы числовых литералов

Возможно, вы попытались применить какой-нибудь метод к числовому литералу (23.toString(2)) и получили синтаксическую ошибку. Это связано со специфическим представлением чисел в JavaScript. Валидная форма для числа 23 - 23. или 23.0 (0 в дробной части можно не указывать).

Когда вы пишете 23.toString(2) JavaScript считает эту запись числом и не понимает, что вызывается метод.

Решением может быть использование скобок или двух точек для указания дробной части (хотя это довольно непонятная запись):

(23).toString(2) // "10111"
23..toString(2)

Не число – это число

Подробное объяснение этого феномена можно найти в статье JS Essentials: Types & Data Structures.

Коротко говоря, NaN является объектом класса Number, но определяется как результат математических операций, значение которых количественно число не является. Правильнее было бы назвать его Invalid Number.

NaN превращает все, с чем имеет дело, в NaN.

const a = 5 + NaN // NaN

Проверка на NaN

Это единственное значение в JavaScript, которое не равно самому себе. Мы можем использовать это, применяя проверку x !== x. Если это условие возвращает true, то x – это NaN.

Помимо этого можно использовать методы Object.is, isNaN и новый метод Number.isNaN. Обратите внимание, два последних метода ведут себя по-разному с нечисловыми значениями.

NaN == NaN // false
NaN === NaN // false

Object.is(NaN, NaN) // true

isNaN(NaN) // true
isNaN('abc') // true

Number.isNaN(NaN) // true
Number.isNaN('abc') // false
Number.isNaN(+'abc') // true

Способы округления чисел

const x = 5.921

// округление вниз
Math.floor(x) // 5

// округление вверх
Math.ceil(x) // 6

// округление по правилам математики
Math.round(x) // 6
Math.round(5.5) // 6

// до нужного количества цифр после точки
x.toFixed(2) // 5.92
x.toPrecision(2) // 5.9

// битовый сдвиг
// работает быстрее, чем Math.floor
// но очень неочевидно для ваших коллег
x >> 0 // 5

Возведение в степень

В JavaScript существует специальный оператор степени – **. Также можно воспользоваться методом Math.pow.

2 ** 2 // 4
let x = 2
x ** = 4 // 16
Math.pow(2, 4) // 16

Генерация случайного числа

Метод Math.random генерирует дробное число в диапазоне от 0 (включая) до 1 (не включая).

Math.random() // 0.7610368478059286

// генерация числа в диапазоне от 0 до 9
// битовый сдвиг работает как Math.floor
Math.random() * 10 >> 0
Math.floor(Math.random() * 10)

// генерация числа в диапазоне [x, y)
const getRandom = (min, max) =>
    Math.floor(Math.random() * (max - min + 1)) + min;

Вот небольшой пример: создадим сет – набор уникальных значений, заполним его случайными числами с помощью метода getRandom и отсортируем:

for (let i of Array(500)) {
   values.add(getRandom(1, 10))
}
[...values].sort((a, b) => a - b)
// [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]

Математические функции

В модуле Math очень много полезных методов, которые вы можете найти в документации. Все они имеют довольно очевидный принцип работы.

Полезные ссылки

Практика работы с числами

Несколько полезных челленджей на codewars.com.

Перевод статьи JavaScript Essentials: Numbers and Math.

Полезные ресурсы для начинающего JavaScript-разработчика

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ

admin
10 июня 2018

Лайфхак: в какой последовательности изучать JavaScript

Огромный инструментарий JS и тонны материалов по нему. С чего начать? Расск...
admin
08 октября 2017

13 ресурсов, чтобы выучить математику

Среди разработчиков часто возникают споры о том, необходимо ли изучать мате...