Skip to content

Latest commit

 

History

History

appendix-data-representation

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 

README.md

Приложение. Представление данных в памяти

Цель

Заглянуть «под капот»: понять, как компьютер хранит целые числа и числа с плавающей точкой, почему возникают переполнения и почему 0.1 + 0.2 != 0.3.

Этот материал не обязателен для написания кода, но даёт глубокое понимание того, как всё устроено.


1. Представление целых чисел

Компьютер хранит всё в двоичном виде (0 и 1).

Целые положительные числа хранятся как обычное двоичное число. Например, число 5 — это 0000 0101.

Дополнительный код (Two's complement)

Как хранятся отрицательные числа? В C++ используется дополнительный код.

Правило:

  1. Берём положительное число в двоичном виде.
  2. Инвертируем все биты (0 → 1, 1 → 0).
  3. Прибавляем 1.

Пример для -5 (тип char, 8 бит):

  1. 5 = 0000 0101
  2. Инверсия: 1111 1010
  3. +1: 1111 1011 — это и есть -5.

Почему так сложно? Чтобы процессор мог складывать числа одной и той же операцией +, не задумываясь о знаке.

Переполнение (Overflow)

У каждого типа есть предел (для int это ±2.1 млрд). Что если прибавить 1 к максимальному числу?

int x = 2147483647; // INT_MAX
x = x + 1;          // ПЕРЕПОЛНЕНИЕ! (Undefined Behavior в C++)

Число «заворачивается» в отрицательное (если это unsigned) или вызывает неопределённое поведение (если signed).


2. Представление чисел с плавающей точкой (IEEE 754)

Дробные числа (float, double) хранятся по стандарту IEEE 754.

Любое число представляется в виде: (-1)^знак * 1.мантисса * 2^экспонента.

В памяти числа раскладываются на три части:

  • Знак (1 бит) — 0 (плюс) или 1 (минус).
  • Экспонента (8 бит для float, 11 для double) — степень двойки.
  • Мантисса (23 бита для float, 52 для double) — значащие цифры.

Почему 0.1 + 0.2 != 0.3?

В десятичной системе 1/3 нельзя записать точно (0.3333...). В двоичной системе так же нельзя точно записать 0.1 (это бесконечная дробь).

Компьютер хранит приближение. Поэтому 0.1 + 0.2 даёт 0.30000000000000004.

Как сравнивать? С заданной точностью (эпсилон):

bool isEqual(double a, double b) {
    return fabs(a - b) < 1e-9;
}

3. Специальные значения IEEE 754

  • +Infinity / -Infinity — бесконечность (например, 1.0 / 0.0).
  • NaN (Not a Number) — «не число» (например, 0.0 / 0.0).
  • NaN не равен даже самому себе! NaN == NaN → false.

Примеры

  • representation.cpp — программа, которая показывает биты чисел и переполнение.

Что дальше

Вернуться к основному курсу.