Числа в JavaScript: типы, преобразования и операции с примерами
Перейти

Числа в JavaScript: типы, преобразования и операции с примерами

#Основы JavaScript  #Синтаксис и типы данных  #Операторы и выражения  
Пройдите тест, узнайте какой профессии подходите
Сколько вам лет
0%
До 18
От 18 до 24
От 25 до 34
От 35 до 44
От 45 до 49
От 50 до 54
Больше 55

Для кого эта статья:

  • Программисты и разработчики, работающие с JavaScript
  • Специалисты по веб-разработке и созданию финансовых приложений
  • Люди, изучающие особенности работы с числами и математическими операциями в JavaScript

Каждый программист на JavaScript однажды сталкивается с сюрпризом: 0.1 + 0.2 !== 0.3. Этот маленький парадокс открывает дверь в удивительный мир чисел в JavaScript — со своими правилами, особенностями и неожиданными поворотами. Точность финансовых расчетов, обработка пользовательского ввода, сложные математические операции — всё это требует глубокого понимания числовых типов. Погрузимся в эту тему, чтобы вы больше никогда не попадались на числовые ловушки и могли писать надежный, предсказуемый код. 📊

Числовые типы в JavaScript: Number и BigInt

JavaScript предлагает два основных типа для работы с числами: Number и BigInt. Понимание их особенностей критически важно для правильного проектирования вычислений.

Number — базовый числовой тип, представляющий как целые, так и дробные значения. Он использует 64-битный формат с плавающей точкой (IEEE 754), что позволяет хранить числа в диапазоне от ±5×10<sup>-324</sup> до ±1.8×10<sup>308</sup>.

BigInt — относительно новый тип (представлен в ES2020), способный представлять целые числа произвольной длины. Он решает проблему ограниченного диапазона Number для целых чисел.

Свойство Number BigInt
Синтаксис создания 42, 3.14 42n, BigInt(42)
Поддержка дробных значений Да Нет
Максимальное безопасное целое Number.MAX_SAFE_INTEGER (2<sup>53</sup>-1) Неограниченно
Производительность Высокая Ниже для больших чисел
Поддержка математических операций Полная Ограниченная, без смешивания типов

Number включает несколько специальных значений:

  • Infinity и -Infinity — представления бесконечности
  • NaN (Not a Number) — результат неопределенных или невозможных операций
  • 0 и -0 — положительный и отрицательный нули (редко встречаются в практике)

Максим, технический директор финтех-стартапа Мы разрабатывали систему для трейдинговой платформы, и наш код периодически давал странные результаты при расчетах крупных сумм. Оказалось, мы наткнулись на предел безопасных целых чисел в JavaScript. Число 9007199254740992 + 1 давало тот же результат, что и 9007199254740992! Переход на BigInt для операций с крупными суммами полностью решил проблему. Но важно помнить — BigInt и Number не совместимы напрямую в операциях, нужна явная конверсия.

При выборе числового типа руководствуйтесь следующими принципами:

  • Используйте Number для большинства обычных вычислений
  • Переходите на BigInt, когда требуется работа с целыми числами за пределами ±2<sup>53</sup>
  • Учитывайте, что BigInt требует больше ресурсов для простых операций
  • Помните о невозможности смешивания типов без явного преобразования

Код для проверки границ числовых типов:

JS
Скопировать код
// Демонстрация пределов типа Number
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991
console.log(Number.MAX_SAFE_INTEGER + 1); // 9007199254740992 
console.log(Number.MAX_SAFE_INTEGER + 2); // 9007199254740992 (ошибка!)

// Использование BigInt для больших чисел
const bigNum = 9007199254740991n;
console.log(bigNum + 1n); // 9007199254740992n
console.log(bigNum + 2n); // 9007199254740993n (корректно!)

Пошаговый план для смены профессии

Преобразование типов: строки и числа в JavaScript

Преобразование между строками и числами — одна из самых частых операций при разработке на JavaScript. От корректности этих преобразований зависит надежность вашего приложения, особенно при обработке пользовательского ввода. 🔄

JavaScript предлагает несколько способов преобразования строк в числа:

  • Number() — строгое преобразование с отклонением некорректного формата
  • parseInt() — извлекает целое число, игнорируя нецифровые символы после первого числа
  • parseFloat() — извлекает число с плавающей точкой
  • Унарный оператор + — краткий способ преобразования, эквивалентный Number()

Анна, ведущий разработчик веб-приложений В одном из проектов мы собирали данные через форму, где пользователи вводили числовые значения. Мы использовали простое преобразование через унарный плюс и столкнулись с неожиданной проблемой: во многих странах Европы десятичным разделителем является запятая, а не точка. Когда немецкий пользователь вводил "10,5", наш код преобразовывал это в NaN. Мы решили проблему, используя интернационализированный парсер, заменяющий запятые на точки перед конвертацией. Также мы добавили валидацию на стороне клиента, которая показывала подсказки о правильном формате ввода.

Для преобразования числа в строку также существует несколько методов:

  • String() — создаёт строковое представление любого значения
  • toString() — метод объекта Number с возможностью указания системы счисления
  • toFixed() — преобразует число в строку с указанным количеством десятичных знаков
  • Конкатенация с пустой строкой num + "" — простой, но менее очевидный способ
Метод преобразования Пример Результат Особенности
Number() Number("123.45") 123.45 Строгое преобразование, возвращает NaN при ошибке
parseInt() parseInt("123.45", 10) 123 Возвращает целое число, требует указания основания
parseFloat() parseFloat("123.45") 123.45 Обрабатывает десятичные числа
Унарный + +"123.45" 123.45 Краткая запись Number(), часто используется в коде
toString() (123.45).toString() "123.45" Можно указать основание системы счисления
toFixed() (123.45).toFixed(1) "123.5" Округляет до указанного количества знаков после запятой

При работе с преобразованиями типов важно помнить о потенциальных ошибках:

JS
Скопировать код
// Потенциальные проблемы и их решения
console.log(parseInt("08")); // В старых браузерах: 0 (восьмеричная система)
console.log(parseInt("08", 10)); // 8 (явное указание десятичной системы)

console.log(Number("10,5")); // NaN (запятая вместо точки)
console.log(Number("10.5")); // 10.5

console.log(+""); // 0 (пустая строка преобразуется в ноль)
console.log(+null); // 0 (null преобразуется в ноль)
console.log(+undefined); // NaN
console.log(+"текст"); // NaN

// Правильная обработка пользовательского ввода
function parseUserInput(input) {
// Заменяем запятые на точки для интернационализации
const normalized = input.replace(/,/g, '.');
const num = parseFloat(normalized);
return isNaN(num) ? null : num;
}

console.log(parseUserInput("10,5")); // 10.5

Базовые и расширенные математические операции в JS

JavaScript предоставляет полный набор инструментов для выполнения математических операций — от элементарных арифметических действий до сложных вычислений. Мастерство в использовании этих инструментов позволяет создавать эффективные алгоритмы и точные расчеты. ➗

Базовые арифметические операторы включают:

  • + (сложение)
  • - (вычитание)
  • * (умножение)
  • / (деление)
  • % (остаток от деления)
  • ** (возведение в степень, ES2016+)

Для более сложных математических операций JavaScript предоставляет объект Math, который содержит методы для тригонометрических, логарифмических и других математических функций.

Наиболее часто используемые методы объекта Math:

  • Math.abs(x) — возвращает абсолютное значение числа
  • Math.ceil(x) — округление вверх
  • Math.floor(x) — округление вниз
  • Math.round(x) — округление к ближайшему целому
  • Math.trunc(x) — удаляет дробную часть (ES2015+)
  • Math.max(...values) — находит максимальное значение
  • Math.min(...values) — находит минимальное значение
  • Math.random() — генерирует псевдослучайное число от 0 до 1
  • Math.pow(x, y) — возведение x в степень y (устаревший аналог оператора **)
  • Math.sqrt(x) — квадратный корень числа

Примеры использования базовых операторов:

JS
Скопировать код
// Базовые арифметические операции
let sum = 10 + 5; // 15
let difference = 10 – 5; // 5
let product = 10 * 5; // 50
let quotient = 10 / 5; // 2
let remainder = 10 % 3; // 1
let power = 10 ** 2; // 100

// Составные операторы присваивания
let x = 5;
x += 3; // x = 8
x -= 2; // x = 6
x *= 2; // x = 12
x /= 4; // x = 3

// Инкремент и декремент
let y = 5;
let z = y++; // z = 5, y = 6 (постфиксный инкремент)
let a = 5;
let b = ++a; // b = 6, a = 6 (префиксный инкремент)

Примеры использования методов объекта Math:

JS
Скопировать код
// Округление и работа с дробями
console.log(Math.round(4.7)); // 5
console.log(Math.round(4.4)); // 4
console.log(Math.ceil(4.4)); // 5
console.log(Math.floor(4.7)); // 4
console.log(Math.trunc(4.7)); // 4

// Поиск минимума и максимума
console.log(Math.min(2, 5, 1, 8, 3)); // 1
console.log(Math.max(2, 5, 1, 8, 3)); // 8

// Генерация случайных чисел
console.log(Math.random()); // случайное число от 0 до <1
// Случайное целое от min до max (включительно)
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max – min + 1)) + min;
}
console.log(getRandomInt(1, 10)); // случайное число от 1 до 10

// Математические функции
console.log(Math.sqrt(16)); // 4 (квадратный корень)
console.log(Math.pow(2, 3)); // 8 (2 в степени 3)
console.log(2 ** 3); // 8 (то же самое с оператором)
console.log(Math.abs(-5)); // 5 (абсолютное значение)

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

JS
Скопировать код
// Классический пример проблемы с плавающей точкой
console.log(0.1 + 0.2); // 0.30000000000000004
console.log(0.1 + 0.2 === 0.3); // false

// Решение: использование допустимой погрешности (эпсилон)
function areEqual(a, b, epsilon = 0.0001) {
return Math.abs(a – b) < epsilon;
}
console.log(areEqual(0.1 + 0.2, 0.3)); // true

// Альтернативное решение: умножение и деление для избегания дробей
console.log((0.1 * 10 + 0.2 * 10) / 10); // 0.3

Методы работы с числами в JavaScript

JavaScript предоставляет множество методов для эффективной работы с числами, от базового форматирования до специализированных вычислений. Освоение этих методов позволяет создавать более читаемый, поддерживаемый код и избегать распространенных ошибок при числовых операциях. 🧮

Основные методы прототипа Number:

  • toFixed(n) — форматирует число, используя фиксированное количество цифр после запятой
  • toPrecision(n) — форматирует число с указанным общим количеством значащих цифр
  • toString([radix]) — преобразует число в строковое представление с возможностью указания основания системы счисления
  • toExponential(n) — возвращает строку с числом в экспоненциальной записи
  • toLocaleString([locales[, options]]) — возвращает строку с числом, форматированным согласно языковым настройкам

Статические методы и свойства объекта Number:

  • Number.isInteger() — проверяет, является ли значение целым числом
  • Number.isFinite() — определяет, является ли значение конечным числом
  • Number.isNaN() — проверяет, является ли значение NaN
  • Number.parseInt() и Number.parseFloat() — парсят строковое значение в число
  • Number.MAX_SAFE_INTEGER и Number.MIN_SAFE_INTEGER — константы, определяющие границы безопасных целых чисел
  • Number.EPSILON — наименьшая разница между представимыми числами
  • Number.MAX_VALUE и Number.MIN_VALUE — максимальное и минимальное положительные числа

Примеры использования методов прототипа Number:

JS
Скопировать код
// Форматирование чисел с фиксированной точкой
const price = 19.99;
console.log(price.toFixed(0)); // "20"
console.log(price.toFixed(1)); // "20.0"
console.log(price.toFixed(2)); // "19.99"
console.log(price.toFixed(3)); // "19.990"

// Форматирование с определенной точностью
const largeNumber = 1234.56789;
console.log(largeNumber.toPrecision(4)); // "1235"
console.log(largeNumber.toPrecision(7)); // "1234.568"

// Преобразование в различные системы счисления
const decimal = 42;
console.log(decimal.toString()); // "42" (десятичная)
console.log(decimal.toString(2)); // "101010" (двоичная)
console.log(decimal.toString(8)); // "52" (восьмеричная)
console.log(decimal.toString(16)); // "2a" (шестнадцатеричная)

// Локализованное форматирование чисел
const bigNum = 1234567.89;
console.log(bigNum.toLocaleString('en-US')); // "1,234,567.89"
console.log(bigNum.toLocaleString('de-DE')); // "1.234.567,89"
console.log(bigNum.toLocaleString('ru-RU')); // "1 234 567,89"

// Форматирование валюты
console.log(bigNum.toLocaleString('en-US', {
style: 'currency',
currency: 'USD'
})); // "$1,234,567.89"

console.log(bigNum.toLocaleString('de-DE', {
style: 'currency',
currency: 'EUR'
})); // "1.234.567,89 €"

Примеры использования статических методов Number:

JS
Скопировать код
// Проверка типов и свойств чисел
console.log(Number.isInteger(42)); // true
console.log(Number.isInteger(42.0)); // true
console.log(Number.isInteger(42.1)); // false

console.log(Number.isFinite(42)); // true
console.log(Number.isFinite(Infinity)); // false
console.log(Number.isFinite(NaN)); // false

console.log(Number.isNaN(NaN)); // true
console.log(Number.isNaN("NaN")); // false (строгая проверка)
console.log(isNaN("NaN")); // true (нестрогая глобальная функция)

// Парсинг чисел
console.log(Number.parseInt("42px", 10)); // 42
console.log(Number.parseFloat("3.14rad")); // 3.14

// Константы и пределы
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991
console.log(Number.MIN_SAFE_INTEGER); // -9007199254740991
console.log(Number.EPSILON); // 2.220446049250313e-16
console.log(Number.MAX_VALUE); // 1.7976931348623157e+308
console.log(Number.MIN_VALUE); // 5e-324

Метод Использование Сценарий применения
toFixed() Отображение финансовых значений Форматирование цен, расчет налогов
toString(16) Работа с цветами, битовыми операциями Преобразование RGB в HEX, битовые маски
toLocaleString() Интернационализация приложений Отображение форматированных чисел для разных регионов
Number.isInteger() Валидация ввода Проверка корректности количества, возраста и т.д.
Number.parseFloat() Обработка пользовательского ввода Парсинг значений из полей форм

Практические советы по работе с методами чисел в JavaScript:

  • Всегда используйте Number.isNaN() вместо глобальной функции isNaN() для строгой проверки NaN
  • При работе с пользовательским вводом всегда указывайте радикс (основание системы счисления) для parseInt: parseInt("08", 10)
  • Используйте toLocaleString() для форматирования чисел в пользовательском интерфейсе — это автоматически учтет региональные особенности
  • Помните о точности toFixed(): метод округляет результат, что может быть критично для финансовых расчетов
  • Для сравнения чисел с плавающей точкой используйте Number.EPSILON в качестве допустимой погрешности

Особенности и ограничения чисел в JavaScript

Понимание особенностей и ограничений чисел в JavaScript критически важно для написания надежного кода. Даже опытные разработчики периодически сталкиваются с неожиданным поведением, которое может привести к труднообнаружимым ошибкам. Рассмотрим основные подводные камни и способы их обхода. ⚠️

Ключевые ограничения и особенности чисел в JavaScript:

  • Проблемы с точностью при операциях с плавающей точкой
  • Ограниченный диапазон безопасных целых чисел
  • Специфическое поведение NaN и Infinity
  • Потеря точности при работе с очень большими или очень маленькими числами
  • Особенности преобразования типов при арифметических операциях

Проблемы с плавающей точкой — самая известная особенность JavaScript. Из-за использования бинарного представления десятичных дробей возникают неожиданные результаты:

JS
Скопировать код
// Классические проблемы с плавающей точкой
console.log(0.1 + 0.2); // 0.30000000000000004
console.log(0.3 – 0.1); // 0.19999999999999998
console.log(0.1 + 0.2 === 0.3); // false

// Решения проблемы с плавающей точкой:

// 1. Использование округления
console.log((0.1 + 0.2).toFixed(1)); // "0.3"

// 2. Использование эпсилон для сравнения
function areFloatsEqual(a, b) {
return Math.abs(a – b) < Number.EPSILON;
}
console.log(areFloatsEqual(0.1 + 0.2, 0.3)); // true

// 3. Использование целых чисел путем масштабирования
console.log((0.1 * 10 + 0.2 * 10) / 10); // 0.3

Ограничения диапазона целых чисел:

JS
Скопировать код
// Демонстрация пределов целых чисел
const maxSafeInt = Number.MAX_SAFE_INTEGER;
console.log(maxSafeInt); // 9007199254740991
console.log(maxSafeInt + 1); // 9007199254740992
console.log(maxSafeInt + 2); // 9007199254740992 (ошибка, должно быть 9007199254740993)

// Решение с использованием BigInt
const bigInt = BigInt(Number.MAX_SAFE_INTEGER);
console.log(bigInt); // 9007199254740991n
console.log(bigInt + 1n); // 9007199254740992n
console.log(bigInt + 2n); // 9007199254740993n (корректно)

Специфическое поведение NaN и Infinity:

JS
Скопировать код
// Необычное поведение NaN
console.log(NaN === NaN); // false
console.log(Number.isNaN(NaN)); // true
console.log(Number.isNaN("строка")); // false
console.log(isNaN("строка")); // true (глобальная функция пытается преобразовать аргумент)

// Использование Infinity
console.log(1 / 0); // Infinity
console.log(-1 / 0); // -Infinity
console.log(Infinity > Number.MAX_VALUE); // true
console.log(Infinity – Infinity); // NaN
console.log(Infinity * 0); // NaN

Потеря точности при работе с очень маленькими значениями:

JS
Скопировать код
// Демонстрация потери точности
console.log(0.0000000000000001 + 0.0000000000000002); // 3e-16
console.log(0.0000000000000001 === 0.00000000000000015); // false
console.log(0.0000000000000001 === 0.0000000000000001); // true

Особенности преобразования типов при арифметических операциях:

JS
Скопировать код
// Неожиданные результаты из-за преобразования типов
console.log(1 + "2"); // "12" (конкатенация строк)
console.log(1 – "2"); // -1 (числовое вычитание)
console.log("2" * 3); // 6 (числовое умножение)
console.log(6 / "2"); // 3 (числовое деление)
console.log(1 + true); // 2 (true преобразуется в 1)
console.log(1 + null); // 1 (null преобразуется в 0)
console.log(1 + undefined); // NaN (undefined преобразуется в NaN)

Рекомендации по работе с ограничениями чисел в JavaScript:

  • Для финансовых расчетов и высокоточных вычислений используйте библиотеки вроде decimal.js или big.js
  • Применяйте BigInt для работы с целыми числами за пределами безопасного диапазона
  • При сравнении чисел с плавающей точкой всегда используйте пороговое значение (эпсилон)
  • Для проверки NaN используйте только Number.isNaN(), а не глобальную функцию isNaN()
  • Будьте осторожны с автоматическими преобразованиями типов — используйте строгое сравнение (===) и явные преобразования
  • Всегда валидируйте пользовательский ввод перед числовыми операциями

Практический пример работы с большими числами и высокой точностью:

JS
Скопировать код
// Пример использования библиотеки decimal.js для финансовых расчетов
// (необходимо подключить библиотеку в проект)

// Некорректный расчет процентов нативными методами
const amount = 1234.56;
const taxRate = 0.21;
const nativeTax = amount * taxRate;
console.log(nativeTax); // 259.2576
console.log(nativeTax.toFixed(2)); // "259.26"

// Если бы мы использовали библиотеку decimal.js:
/*
import { Decimal } from 'decimal.js';

const amount = new Decimal(1234.56);
const taxRate = new Decimal(0.21);
const tax = amount.times(taxRate);
console.log(tax.toString()); // "259.2576"
console.log(tax.toFixed(2)); // "259.26"
*/

JavaScript не идеален в вопросах работы с числами, но понимание его ограничений и применение соответствующих техник позволяет построить надежные, точные вычисления. Помните: числа в JavaScript — это инструмент с определенными свойствами, и как любым инструментом, им нужно уметь пользоваться. Сконцентрируйтесь на безопасной обработке крайних случаев, чёткой валидации входных данных и использовании специализированных библиотек для сложных расчётов — и вы никогда не будете бояться числовых операций в своих проектах.

Проверь как ты усвоил материалы статьи
Пройди тест и узнай насколько ты лучше других читателей
Какой специальный тип в JavaScript обозначает, что значение не является числом?
1 / 5

Станислав Плотников

фронтенд-разработчик

Свежие материалы

Загрузка...