Кратко
СкопированоТип данных «число» (number
) содержит числа с плавающей точкой в диапазоне от -(253 − 1) до 253 − 1, а также специальные значения Infinity
, -
и NaN
.
Для этого типа данных определены стандартные арифметические операции сложения +
, вычитания -
, умножения *
, деления /
, взятия остатка от целочисленного деления %
, сравнения >
, <
, >
, <
, =
, =
, !
, !
.
В JavaScript отсутствует отдельный тип данных для целых чисел, для целых чисел также используется тип number
.
Как пишется
СкопированоДля записи чисел используются цифры, для разделения целой и десятичной части используется точка:
const int = 4const decimal = 0.101const sameDecimal = .101
const int = 4 const decimal = 0.101 const sameDecimal = .101
Можно использовать экспоненциальную запись. Например, один миллион в экспоненциальной записи:
const scientific = 1e6
const scientific = 1e6
Числа так же могут быть представлены в двоичном, восьмеричном или шестнадцатеричном виде. Такие числа начинаются с приставки 0b
, 0o
, 0x
соответственно. При выводе на экран они будут преобразованы в десятичную систему счисления:
const binary = 0b11console.log(binary)// 3const octal = 0o77console.log(octal)// 63const hexadecimal = 0xFFconsole.log(hexadecimal)// 255
const binary = 0b11 console.log(binary) // 3 const octal = 0o77 console.log(octal) // 63 const hexadecimal = 0xFF console.log(hexadecimal) // 255
Как понять
СкопированоЧисло с плавающей точкой
СкопированоЧисло в JavaScript представлено в виде 64-битного формата IEEE-754. Формат хранит произвольное число в виде трёх значений: 1 бит на знак числа, 52 бита значения числа и ещё 11 бит местоположения точки. С таким подходом можно эффективно хранить значения в большом диапазоне от -(253 − 1) до 253 − 1.
Из-за того, что положение точки в числе хранится отдельным значением, формат и называется числом с плавающей точкой (floating point number).
Проблема этого представления в том, что оно не может представить числа абсолютно точно, а только с некоторой погрешностью.
Неточные вычисления
СкопированоВ десятичной системе счисления есть числа, которые не могут быть записаны точно. Например, треть ¹⁄₃ записывается как бесконечная дробь 0.33(3).
Компьютер хранит данные в двоичном виде — наборе нулей и единиц. В этой системе счисления тоже есть дроби, которые не могут быть записаны точно. В этом случае формат округляет значение до ближайшего представимого. При арифметических операциях эти неточности складываются и приводят к эффектам, подобным этому:
console.log(0.2 + 0.7)// 0.8999999999999999
console.log(0.2 + 0.7) // 0.8999999999999999
Это не ошибка JavaScript, а фундаментальная особенность хранения дробных чисел в памяти компьютера, с ней нужно уметь работать. Для уменьшения эффекта используется комбинация подходов — использовать как можно меньше дробных значений, а когда этого невозможно избежать — округлять числа, тем самым сбрасывая накопившийся остаток.
Например, если ваша система работает с деньгами, то лучше хранить цены в копейках или центах. Это позволит избежать большого количества операций с дробями. Для вывода цен можно пользоваться методом to
, который округлит число до указанного разряда:
const priceInCents = 15650const discount = priceInCents * 0.33const total = (priceInCents - discount) / 100console.log(total.toFixed(2))// 104.86
const priceInCents = 15650 const discount = priceInCents * 0.33 const total = (priceInCents - discount) / 100 console.log(total.toFixed(2)) // 104.86
Похожую проблему можно наблюдать при сравнении очень маленьких и очень больших чисел. В таких случаях из-за округления точность теряется и различные числа компьютер представляет одинаковыми:
const small = 0.11111111111111111const smaller = 0.11111111111111110console.log(small.toFixed(20))// 0.11111111111111110494console.log(smaller.toFixed(20))// 0.11111111111111110494console.log(small === smaller)// true
const small = 0.11111111111111111 const smaller = 0.11111111111111110 console.log(small.toFixed(20)) // 0.11111111111111110494 console.log(smaller.toFixed(20)) // 0.11111111111111110494 console.log(small === smaller) // true
Специальные значения
СкопированоСтандарт IEEE-754 определяет три специальных значения. Эти значения принадлежат типу number
, но не работают, как обычные числа:
- бесконечность
Infinity
; - минус бесконечность
-
;Infinity - не число (not a number)
NaN
.
Бесконечности используются, чтобы определить результат некоторых арифметических операций. Например, деление на ноль в JavaScript вернёт бесконечность:
console.log(5 / 0)// Infinityconsole.log(-3 / 0)// -Infinity
console.log(5 / 0) // Infinity console.log(-3 / 0) // -Infinity
Если попытаться создать число, которое находится вне диапазона доступных чисел, результатом будет тоже бесконечность:
console.log(1e999)// Infinity
console.log(1e999) // Infinity
Значение NaN
используется, чтобы сообщить об операции, результатом которой оказалось не число. В JavaScript существует пять операций, которые могут вернуть NaN
:
- ошибка парсинга числа (например, при попытке превратить строку в число
parse
);Int ( 'привет' ) - результат математической операции не находится в поле действительных чисел (например, взятие корня от -1);
- один из операндов в арифметической операции —
NaN
(5 +
);Na N - результат арифметической операции не определён для переданных операндов (
undefined + undefined
); - арифметическая операция со строкой, кроме сложения (
'привет' * 5
).
Согласно спецификации NaN
не равен самому себе. Проверить, что в переменной хранится NaN
, простым сравнением не получится:
const result = NaNconsole.log(result === NaN)// false
const result = NaN console.log(result === NaN) // false
Для проверки на NaN
пользуйтесь функцией Number
, которая возвращает true
если переданное значение — NaN
:
const result = NaNconsole.log(Number.isNaN(result))// true
const result = NaN console.log(Number.isNaN(result)) // true
Для проверки, что значение в переменной является конечным числом, а не специальным значением, пользуйтесь функцией Number
, она возвращает true
, если переданный аргумент — число.
const inf = Infinityconst nan = NaNconst num = 99999console.log(Number.isFinite(inf))// falseconsole.log(Number.isFinite(nan))// falseconsole.log(Number.isFinite(num))// true
const inf = Infinity const nan = NaN const num = 99999 console.log(Number.isFinite(inf)) // false console.log(Number.isFinite(nan)) // false console.log(Number.isFinite(num)) // true
Операции с числами
СкопированоС числами можно выполнять стандартные математические операции, для определения приоритета операций пользуются скобками:
const a = 5const b = 10console.log(-a)// -5console.log(a + b)// 15console.log(a - b)// -5console.log(a / b)// 0.5console.log(a * b)// 50console.log((a + b) / 10)// 1.5
const a = 5 const b = 10 console.log(-a) // -5 console.log(a + b) // 15 console.log(a - b) // -5 console.log(a / b) // 0.5 console.log(a * b) // 50 console.log((a + b) / 10) // 1.5
Существует оператор взятия остатка от деления нацело %
:
console.log(5 % 2)// 1, потому что 5 = 2 * 2 + 1console.log(5 % 3)// 2, потому что 5 = 1 * 3 + 2console.log(5 % 5)// 0, потому что 5 = 5 * 1 + 0
console.log(5 % 2) // 1, потому что 5 = 2 * 2 + 1 console.log(5 % 3) // 2, потому что 5 = 1 * 3 + 2 console.log(5 % 5) // 0, потому что 5 = 5 * 1 + 0
Возведения в степень **
:
console.log(2 ** 4)// 16
console.log(2 ** 4) // 16
Для округления, взятия корней и других математических операций в JavaScript существует отдельный модуль Math
.
Операторы сравнения возвращают булево значение:
console.log(5 > 10)// falseconsole.log(5 >= 10)// falseconsole.log(5 < 10)// trueconsole.log(10 <= 10)// trueconsole.log(5 == 10)// falseconsole.log(5 === 10)// falseconsole.log(5 != 10)// trueconsole.log(5 !== 10)// true
console.log(5 > 10) // false console.log(5 >= 10) // false console.log(5 < 10) // true console.log(10 <= 10) // true console.log(5 == 10) // false console.log(5 === 10) // false console.log(5 != 10) // true console.log(5 !== 10) // true
Числовой разделитель
СкопированоВ спецификации EcmaScript 2021 года (ES12) появилась возможность добавлять в числа разделители. Например:
const number = 1_000_000_000console.log(number)// 1000000000
const number = 1_000_000_000 console.log(number) // 1000000000
Разделители делают большие числа более читаемыми, внешне выделяя разряды чисел.
const integer = 1_234_567_890const float = 0.123_456_789
const integer = 1_234_567_890 const float = 0.123_456_789
Разделители доступны для чисел других счислений и Big
:
const binary = 0b0101_1111_0001const hex = 0x12_AB_34_CDconst bigInt = 1_234_567_890n
const binary = 0b0101_1111_0001 const hex = 0x12_AB_34_CD const bigInt = 1_234_567_890n
Дополнительные методы
СкопированоСам по себе примитивный тип «число» не имеет методов. Когда происходит вызов метода у числа, оно автоматически оборачивается в специальную обёртку, которая и содержит методы:
const num = 99.99console.log(num.toFixed(1))// 100.0
const num = 99.99 console.log(num.toFixed(1)) // 100.0
Часто используемые методы обёртки, такие как to
, to
и to
, описаны в отдельной статье.
На собеседовании
Скопировано отвечает
СкопированоОтвет очень простой – нужно воспользоваться специальной функцией Number
. В качестве аргумента нужно передать проверяемую переменную.
Вас может запутать формулировка вопроса: typeof possibly
. Это же not a number, подумаете вы. Дело в том, что NaN
используется для обозначения результатов вычислений, в которых «что-то пошло не так». Можете думать о NaN
так: «Тут должно быть число, но вычисление сломалось». Это может произойти, если захотите вычислить квадратный корень из -1
. В результате получится комплексное число, с которым наш браузер из коробки работать не умеет.
Неправильным ответом на этот вопрос будет вот такая проверка:
possiblyWrongNumber === NaN
possiblyWrongNumber === NaN
Однако в ней уже содержится ответ на более хитрый дополнительный вопрос:
❓ Представим себе, что функции Number
не существует. Как в таком случае проверить, что значение переменной possibly
не является NaN
? Условие typeof possibly
по-прежнему выполняется.
Ответ такой: просто нужно сравнить значение переменной possibly
с самим собой. Если они равны, значит в переменной не NaN
:
possiblyWrongNumber === possiblyWrongNumber
possiblyWrongNumber === possiblyWrongNumber