NodeJS Back-end Инженер

NodeJS Back-end Инженер

Роадмап навыков для прокачки

Чем INT отличается от FLOAT?

DatabasesSQLTypes

Основная идея

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

Ключевые аспекты

  • Точность — INT всегда точен, FLOAT может иметь погрешности округления
  • Диапазон — FLOAT может хранить числа до 10³⁸, INT ограничен миллиардами
  • Дробные числа — INT не может хранить дробную часть, FLOAT может
  • Сравнение — INT сравнивается точно, FLOAT требует учёта погрешности

Плюсы INT

  • Абсолютная точность вычислений
  • Быстрые операции сравнения и индексации
  • Предсказуемое поведение
  • Меньше места при малых значениях

Плюсы FLOAT

  • Хранение очень больших и очень малых чисел
  • Дробные значения (проценты, координаты)
  • Научные вычисления с экспоненциальной записью

Частые ошибки на собеседованиях

  • Используют FLOAT для денег — это критическая ошибка, нужен DECIMAL
  • Сравнивают FLOAT через = — из-за погрешности 0.1 + 0.2 != 0.3
  • Не понимают разницу между FLOAT и DOUBLE — DOUBLE имеет двойную точность
  • Путают FLOAT с DECIMAL — DECIMAL хранит точные десятичные дроби

Введение и проблематика

Выбор между INT и FLOAT — это не просто вопрос "целые vs дробные". Это фундаментальное решение о том, нужна ли вам абсолютная точность или возможность работать с очень большими/малыми числами.

🚫

Использование FLOAT для хранения денежных сумм — классическая ошибка, которая приводит к финансовым потерям из-за погрешностей округления.

Когда это важно?

Представьте: вы храните цену товара 19.99 в FLOAT. После нескольких вычислений получаете 19.989999999999998. При отображении это может округлиться неправильно, а при суммировании миллионов транзакций погрешность становится заметной.


Базовая теория

Как хранятся числа

graph TD A[Числовые типы] --> B[Целые - INT] A --> C[С плавающей точкой - FLOAT] A --> D[Фиксированная точность - DECIMAL] B --> E[Точное хранение] C --> F[Приблизительное хранение] D --> G[Точные десятичные дроби]

INT — целые числа

INT хранит целые числа в двоичном формате. Каждое значение представлено точно, без потери данных.

text
Число 42 в INT (32 бита):
00000000 00000000 00000000 00101010

FLOAT — числа с плавающей запятой

FLOAT использует стандарт IEEE 754. Число разбивается на:

  • Знак (1 бит)
  • Экспонента (8 бит для FLOAT, 11 для DOUBLE)
  • Мантисса (23 бита для FLOAT, 52 для DOUBLE)
text
Число 0.1 в FLOAT:
Не может быть представлено точно!
Хранится как ≈ 0.100000001490116119384765625

Сравнение типов

ХарактеристикаINTFLOATDOUBLEDECIMAL
Размер4 байта4 байта8 байтПеременный
ТочностьАбсолютная~7 цифр~15 цифрТочная
Дробная частьНетДаДаДа
Макс. значение2.1×10⁹3.4×10³⁸1.8×10³⁰⁸10⁶⁵
Для денегНет❌ Нет❌ Нет✅ Да

Практические примеры

Проблема точности FLOAT

sql
-- Создаём таблицу
CREATE TABLE float_test (value FLOAT);
 
-- Вставляем "простое" число
INSERT INTO float_test VALUES (0.1);
 
-- Проверяем
SELECT value, value * 3 AS multiplied FROM float_test;
 
-- Ожидаем: 0.1 и 0.3
-- Получаем: 0.10000000149... и 0.30000000447...
⚠️

Никогда не сравнивайте FLOAT через равенство! Используйте диапазон погрешности.

sql
-- ❌ Неправильно
SELECT * FROM products WHERE price = 19.99;
 
-- ✅ Правильно для FLOAT
SELECT * FROM products WHERE ABS(price - 19.99) < 0.001;
 
-- ✅ Лучше — используйте DECIMAL для цен
CREATE TABLE products (
    id INT PRIMARY KEY,
    price DECIMAL(10, 2)  -- 10 цифр всего, 2 после запятой
);

Когда использовать каждый тип

sql
-- INT: счётчики, ID, количество
CREATE TABLE orders (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    user_id INT UNSIGNED NOT NULL,
    item_count SMALLINT UNSIGNED,
    status TINYINT  -- 0, 1, 2, 3...
);
 
-- Идеально для:
-- • Идентификаторов
-- • Количества (штук, людей)
-- • Статусов и флагов
-- • Возраста, года

Пограничные кейсы

Переполнение и потеря точности

sql
-- INT: переполнение при превышении диапазона
INSERT INTO test (int_col) VALUES (2147483648);
-- Ошибка: Out of range value
 
-- FLOAT: потеря точности при больших числах
SELECT CAST(123456789 AS FLOAT);
-- Может вернуть: 123456792 (потеря младших разрядов!)
 
-- FLOAT: накопление ошибок
SELECT 0.1 + 0.1 + 0.1 + 0.1 + 0.1 +
       0.1 + 0.1 + 0.1 + 0.1 + 0.1;
-- Ожидаем: 1.0
-- Можем получить: 0.9999999999999999 или 1.0000000000000002
🚫

При работе с большими целыми числами (больше 16 777 216 для FLOAT) возможна потеря точности даже для целой части!

Индексирование

sql
-- INT индексируется эффективно
CREATE INDEX idx_user_id ON orders(user_id);  -- Быстро
 
-- FLOAT можно индексировать, но поиск по = работает плохо
CREATE INDEX idx_price ON products(price);
SELECT * FROM products WHERE price = 19.99;  -- Может не найти!
 
-- Для FLOAT лучше использовать диапазоны
SELECT * FROM products WHERE price BETWEEN 19.98 AND 20.00;

Производительность

ОперацияINTFLOAT
СравнениеОчень быстроБыстро
АрифметикаБыстроБыстро (FPU)
ИндексацияЭффективноМенее эффективно
СортировкаБыстроБыстро
Хранение4 байта4 байта

Плюсы и минусы

ТипПлюсыМинусы
INTТочность, скорость, простотаНет дробной части
FLOATБольшой диапазон, дробные числаПогрешности, сложности сравнения
DOUBLEБольше точности чем FLOAT8 байт, всё ещё не точен
DECIMALАбсолютная точностьМедленнее, больше места

Вопросы интервьюера

Q: Можно ли использовать FLOAT для хранения цен?

Категорически нет! Используйте DECIMAL. Погрешности FLOAT приводят к ошибкам в финансовых расчётах.

Q: Чем FLOAT отличается от DOUBLE?

DOUBLE имеет двойную точность: 8 байт вместо 4, ~15 значащих цифр вместо ~7. Используйте DOUBLE для координат и научных расчётов.

Q: Почему 0.1 + 0.2 != 0.3 в FLOAT?

0.1 и 0.2 не могут быть точно представлены в двоичной системе. Сумма их приблизительных представлений даёт приблизительный результат, не равный точно 0.3.

Q: Когда использовать INT вместо FLOAT?

Всегда, когда значения целые: ID, количество, статусы, возраст. INT быстрее, точнее и проще в использовании.


Источники