Тип number в TypeScript
Целые числа, дробные числа, NaN, Infinity и методы Math
Добро пожаловать!
Сегодня мы начинаем изучение примитивных типов TypeScript — основы, без которой невозможно написать ни одну строку кода. Первый тип, с которым мы познакомимся, — это number. Это один из самых часто используемых типов в любом языке программирования. Числа окружают нас повсюду: возраст пользователя, цена товара, координаты на карте, количество элементов в массиве. В TypeScript все числа — и целые, и дробные — относятся к одному типу number.
Цели урока
Что такое тип number?
Тип number в TypeScript предназначен для представления всех числовых значений. В отличие от некоторых других языков программирования (например, Java или C++), TypeScript не разделяет целые и дробные числа на отдельные типы. Всё — и 42, и 3.14 — относится к типу number.
Пример: Объявление числовых переменных
// Целые числа
let возраст: number = 25;
let количество_студентов: number = 30;
let код_страны: number = 7;
// Дробные числа
let рост: number = 1.78;
let цена: number = 99.99;
let pi: number = 3.14159;
// Отрицательные числа
let температура: number = -15;
let долг: number = -500.50;
// Научная запись
let Авогадро: number = 6.022e23; // 6.022 × 10²³
console.log(возраст); // 25
console.log(цена); // 99.99
console.log(Авогадро); // 6.022e+23
Важно понимать
В JavaScript (а значит и в TypeScript) все числа хранятся как 64-битные числа с плавающей запятой (двойной точности). Это означает, что TypeScript может работать с числами от приблизительно -5 × 10⁻³⁰⁸ до 5 × 10³⁰⁸, но точность ограничена approximately 15-17 значащими цифрами.
Целые и дробные числа
Хотя TypeScript объединяет все числа в один тип, важно понимать разницу между целыми и дробными числами, так как это влияет на поведение вычислений и точность результатов.
Целые числа (Integers)
let a: number = 42;
let b: number = -100;
let c: number = 0;
// Шестнадцатеричные
let hex: number = 0xFF; // 255
// Двоичные
let bin: number = 0b1010; // 10
// Восьмеричные
let oct: number = 0o77; // 63
Дробные числа (Floats)
let x: number = 3.14;
let y: number = -0.5;
let z: number = 2.0; // Также number!
// Научная запись
let small: number = 1.5e-10; // 0.00000000015
let big: number = 1.5e10; // 15000000000
Проблема точности
// Классическая проблема с плавающей запятой
let result: number = 0.1 + 0.2;
console.log(result); // 0.30000000000000004
console.log(result === 0.3); // false!
// Как решить:
console.log(Math.abs(result - 0.3) < Number.EPSILON); // true
// Или округлить до нужного количества знаков
letточный: number = Math.round((0.1 + 0.2) * 100) / 100;
console.log(точный); // 0.3
Это не баг, а особенность представления дробных чисел в компьютере. Все языки программирования, использующие IEEE 754 стандарт, сталкиваются с этой проблемой. Запомните это правило: никогда не сравнивайте дробные числа напрямую!
Особые числовые значения
Помимо обычных чисел, тип number включает несколько особых значений, которые важно знать каждому разработчику.
NaN (Not a Number)
NaN — это значение, которое возникает, когда математическая операция не может дать осмысленный результат. Например, деление нуля на ноль или попытка преобразовать нечисловую строку в число.
// Когда возникает NaN
let a: number = 0 / 0; // NaN
let b: number = Math.sqrt(-1); // NaN
let c: number = parseInt("abc"); // NaN
let d: number = Infinity - Infinity; // NaN
// Свойства NaN
console.log(typeof NaN); // "number" (!)
console.log(NaN === NaN); // false (!!)
console.log(isNaN(NaN)); // true
console.log(Number.isNaN(NaN)); // true (более надёжный метод)
// Как проверить на NaN
let значение: number = NaN;
// Правильные способы проверки:
if (Number.isNaN(значение)) {
console.log("Это NaN!");
}
// Неправильный способ (не используйте это):
if (значение !== значение) {
console.log("Это тоже NaN!");
}
Почему NaN !== NaN? — Это особенность стандарта IEEE 754. Считается, что если два значения не определены, их нельзя считать равными. Всегда используйте Number.isNaN() для проверки.
Infinity и -Infinity
Infinity и -Infinity представляют бесконечность и отрицательную бесконечность соответственно.
// Когда возникает Infinity
let inf: number = 1 / 0; // Infinity
let negInf: number = -1 / 0; // -Infinity
let big: number = 1e308 * 10; // Infinity
// Свойства
console.log(typeof Infinity); // "number"
console.log(Infinity > 1000000); // true
console.log(-Infinity < -1000000); // true
// Проверка
console.log(isFinite(42)); // true
console.log(isFinite(Infinity)); // false
console.log(Number.isFinite(Infinity)); // false
// Полезные константы
console.log(Number.MAX_VALUE); // 1.7976931348623157e+308
console.log(Number.MIN_VALUE); // 5e-324 (самое маленькое положительное)
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991 (2⁵³ - 1)
console.log(Number.MIN_SAFE_INTEGER); // -9007199254740991
Полезные методы работы с числами
// Преобразование в число
let str1: string = "123";
let num1: number = Number(str1); // 123
let num2: number = parseInt("45abc"); // 45
let num3: number = parseFloat("3.14"); // 3.14
let num4: number = +"+99.5"; // 99.5
// Проверка типов
console.log(Number.isInteger(42)); // true
console.log(Number.isInteger(3.14)); // false
console.log(Number.isFinite(42)); // true
console.log(Number.isNaN(NaN)); // true
// Округление
let число: number = 3.7;
console.log(Math.round(число)); // 4 (округление)
console.log(Math.ceil(число)); // 4 (округление вверх)
console.log(Math.floor(число)); // 3 (округление вниз)
console.log(Math.trunc(число)); // 3 (отсечение дробной части)
console.log(Math.round(-3.7)); // -4 (округление)
Объект Math
Объект Math предоставляет множество полезных методов и констант для работы с числами. Давайте рассмотрим самые важные из них.
Математические функции
Math.abs(-5) // 5 (модуль)
Math.sqrt(16) // 4 (квадратный корень)
Math.pow(2, 10) // 1024 (степень)
Math.cbrt(27) // 3 (кубический корень)
Math.log(100) // 4.605 (натуральный логарифм)
Math.log2(8) // 3 (логарифм по основанию 2)
Math.log10(100) // 2 (десятичный логарифм)
Тригонометрия
Math.sin(Math.PI / 2) // 1
Math.cos(Math.PI) // -1
Math.tan(0) // 0
Math.asin(1) // π/2
Math.acos(-1) // π
Math.atan(1) // π/4
Math.atan2(1, 1) // π/4
Случайные числа
// Случайное число от 0 до 1
Math.random()
// Случайное целое от min до max
function случайное(
min: number,
max: number
): number {
return Math.floor(
Math.random() * (max - min + 1) + min
);
}
случайное(1, 10) // 1-10
Константы Math
Math.PI // 3.141592653589793
Math.E // 2.718281828459045
Math.LN2 // 0.6931471805599453
Math.LN10 // 2.302585092994046
Math.SQRT2 // 1.4142135623730951
Практический пример: Калькулятор площади
function площадьКруга(радиус: number): number {
return Math.PI * Math.pow(радиус, 2);
}
function площадьТреугольника(
основание: number,
высота: number
): number {
return 0.5 * основание * высота;
}
function гипотенуза(а: number, б: number): number {
return Math.sqrt(Math.pow(а, 2) + Math.pow(б, 2));
}
// Использование
console.log(`Площадь круга: ${площадьКруга(5).toFixed(2)}`);
console.log(`Площадь треугольника: ${площадьТреугольника(10, 5)}`);
console.log(`Гипотенуза: ${гипотенуза(3, 4)}`);
Преобразование чисел
Часто возникает необходимость преобразовать значения разных типов в числа или наоборот. Давайте изучим основные способы преобразования.
Способы преобразования в число
// 1. Функция Number()
let a: number = Number("123"); // 123
let b: number = Number("12.5"); // 12.5
let c: number = Number(true); // 1
let d: number = Number(false); // 0
let e: number = Number(null); // 0
let f: number = Number(undefined); // NaN
let g: number = Number("abc"); // NaN
// 2. Унарный плюс (самый быстрый способ)
let x = +"42"; // 42
let y = +"3.14"; // 3.14
let z = +"abc"; // NaN
// 3. parseInt() - для целых чисел
let p1 = parseInt("123abc"); // 123
let p2 = parseInt("abc123"); // NaN
let p3 = parseInt("101", 2); // 5 (двоичная система)
let p4 = parseInt("FF", 16); // 255 (шестнадцатеричная)
// 4. parseFloat() - для дробных чисел
let f1 = parseFloat("3.14abc"); // 3.14
let f2 = parseFloat("abc3.14"); // NaN
Рекомендация
Используйте Number() для общих преобразований, parseInt() когда нужно извлечь целое число из строки, и унарный плюс + для кратких преобразований в понятном контексте. Избегайте new Number() — это создает объект, а не примитив.
Форматирование чисел
TypeScript (и JavaScript) предоставляют несколько способов форматировать числа для вывода на экран.
let число: number = 1234567.891;
// toFixed() - фиксированное количество знаков после запятой
console.log(число.toFixed(2)); // "1234567.89"
console.log(число.toFixed(0)); // "1234568"
// toPrecision() - общее количество значащих цифр
console.log(число.toPrecision(5)); // "1.2346e+6"
// toExponential() - научная запись
console.log(число.toExponential(2)); // "1.23e+6"
// toLocaleString() - форматирование с учётом локали
console.log(число.toLocaleString('ru-RU')); // "1 234 567,891"
console.log(число.toLocaleString('en-US')); // "1,234,567.891"
// parseInt и parseFloat для обратного преобразования
let обратно: string = "1234567.891";
console.log(parseInt(обратно)); // 1234567
console.log(parseFloat(обратно)); // 1234567.891
Практический пример: Форматирование валюты
function форматироватьВалюту(
сумма: number,
валюта: string = "₽"
): string {
return сумма.toLocaleString('ru-RU', {
style: 'decimal',
minimumFractionDigits: 2,
maximumFractionDigits: 2
}) + " " + валюта;
}
console.log(форматироватьВалюту(1234567.89)); // "1 234 567,89 ₽"
console.log(форматироватьВалюту(42.5)); // "42,50 ₽"
console.log(форматироватьВалюту(0, "$")); // "0,00 $"
Частые ошибки
Давайте рассмотрим типичные ошибки, которые допускают начинающие разработчики при работе с числами.
Ошибка 1: Сравнение дробных чисел
// Неправильно
if (0.1 + 0.2 === 0.3) { ... } // Всегда false!
// Правильно
if (Math.abs(0.1 + 0.2 - 0.3) < Number.EPSILON) { ... }
Дробные числа с плавающей запятой не могут быть представлены точно в двоичной системе.
Ошибка 2: Потеря точности больших чисел
// Проблема
let bigNumber = 9007199254740992;
console.log(bigNumber === bigNumber + 1); // true (!)
// Решение: используйте BigInt для очень больших чисел
let huge: bigint = 9007199254740992n;
console.log(huge === huge + 1n); // false
Числа больше Number.MAX_SAFE_INTEGER теряют точность.
Ошибка 3: Использование == вместо ===
// Проблема
console.log(0 == false); // true
console.log(0 == ""); // true
console.log("" == false); // true
// Решение: всегда используйте ===
console.log(0 === false); // false
console.log(0 === ""); // false
Оператор == выполняет приведение типов, что может привести к неожиданным результатам.
Ошибка 4: Деление на ноль
// Не вызывает ошибку, но даёт Infinity
console.log(1 / 0); // Infinity
console.log(-1 / 0); // -Infinity
console.log(0 / 0); // NaN
// Всегда проверяйте делитель!
function безопасноеДеление(a: number, b: number): number {
if (b === 0) {
throw new Error("Деление на ноль невозможно");
}
return a / b;
}
Деление на ноль не вызывает ошибку в JavaScript/TypeScript, но даёт Infinity или NaN.
Практические примеры
Давайте закрепим изученное материал на практических примерах, которые вы сможете использовать в своих проектах.
Пример 1: Калькулятор скидки
function рассчитатьСкидку(
цена: number,
процентСкидки: number
): { стараяЦена: number; новаяЦена: number; экономия: number } {
if (процентСкидки < 0 || процентСкидки > 100) {
throw new Error("Процент скидки должен быть от 0 до 100");
}
const экономия = цена * (процентСкидки / 100);
const новаяЦена = цена - экономия;
return {
стараяЦена: цена,
новаяЦена: Math.round(новаяЦена * 100) / 100,
экономия: Math.round(экономия * 100) / 100
};
}
const результат = рассчитатьСкидку(1000, 15);
console.log(`Старая цена: ${результат.стараяЦена}₽`);
console.log(`Новая цена: ${результат.новаяЦена}₽`);
console.log(`Вы сэкономили: ${результат.экономия}₽`);
Пример 2: Генератор паролей
function сгенерироватьПароль(длина: number): string {
const символы = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%";
let пароль = "";
for (let i = 0; i < длина; i++) {
const индекс = Math.floor(Math.random() * символы.length);
пароль += символы[индекс];
}
return пароль;
}
console.log(сгенерироватьПароль(12)); // "aB3$kL9!mN2@"
Пример 3: Конвертер единиц измерения
type ЕдиницаДлины = "мм" | "см" | "м" | "км";
const коэффициенты: Record<ЕдиницаДлины, number> = {
"мм": 0.001,
"см": 0.01,
"м": 1,
"км": 1000
};
function конвертировать(
значение: number,
из: ЕдиницаДлины,
в: ЕдиницаДлины
): number {
const вМетры = значение * коэффициенты[из];
return вМетры / коэффициенты[в];
}
console.log(конвертировать(100, "см", "м")); // 1
console.log(конвертировать(1, "км", "м")); // 1000
console.log(конвертировать(2500, "мм", "км")); // 0.0025
Подведём итоги
Вы изучили:
- Тип
number— все числа в одном типе - Целые и дробные числа
- Особые значения:
NaNиInfinity - Методы объекта
Math - Преобразование и форматирование чисел
Важно помнить:
- Не сравнивайте дробные числа напрямую
- Используйте
Number.isNaN()вместоisNaN() - Проверяйте делитель перед делением
- Будьте осторожны с большими числами
- Используйте
BigIntдля очень больших целых чисел
Тест по типу number
10 вопросов