Кратко
СкопированоТип данных «число» (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
Если в математическом выражении есть NaN, в результате тоже получится NaN. Единственное исключение — возведение в нулевую степень. NaN ** 0 = 1.
Для проверки, что значение в переменной является конечным числом, а не специальным значением, используйте функцию Number. Она возвращает true, если переданный аргумент — число, кроме Infinity.
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