Представление вещественных чисел в памяти компьютера
Вещественные числа (числа с плавающей запятой) в компьютере представляются в особом формате, который позволяет хранить как очень малые, так и очень большие числа.
Вещественное число — число с дробной частью, которое может быть представлено в экспоненциальной форме: \( A = m \times q^p \), где:
- \( m \) — мантисса (значащая часть числа)
- \( q \) — основание системы счисления
- \( p \) — порядок (экспонента)
Структура представления вещественного числа
Нормализованная запись числа
Для увеличения точности представления чисел используется нормализованная запись, при которой мантисса принимает значения:
Это означает, что первая цифра мантиссы после запятой в системе счисления с основанием q всегда отлична от нуля.
Пример: Представим число 123.45 в нормализованном виде:
\( 123.45 = 0.12345 \times 10^3 \)
Здесь мантисса = 0.12345, порядок = 3
Формат IEEE 754
Стандарт IEEE 754 определяет форматы представления чисел с плавающей запятой. Наиболее распространенные:
| Тип | Общий размер (бит) | Разрядность мантиссы | Разрядность порядка | Смещение порядка |
|---|---|---|---|---|
| Single (float) | 32 | 23 бита | 8 бит | 127 |
| Double (double) | 64 | 52 бита | 11 бит | 1023 |
Пример представления числа 13.25 в формате IEEE 754 (single precision):
- Преобразуем в двоичную систему: 13.2510 = 1101.012
- Нормализуем: 1.10101 × 23
- Определяем части:
- Знак: 0 (число положительное)
- Порядок: 3 + 127 = 130 = 100000102
- Мантисса: 10101000000000000000000 (23 бита)
Представление числа 13.25 в формате IEEE 754 (32 бита)
Диапазон значений вещественных чисел
Диапазон представимых чисел зависит от количества бит, отведенных под порядок.
| Тип | Минимальное по модулю | Максимальное по модулю | Десятичных знаков |
|---|---|---|---|
| Single (float) | 1.2 × 10-38 | 3.4 × 1038 | 7-8 |
| Double (double) | 2.2 × 10-308 | 1.8 × 10308 | 15-16 |
Особые значения:
- Ноль: все биты порядка и мантиссы равны 0
- Бесконечность: все биты порядка равны 1, мантисса равна 0
- NaN (Not a Number): все биты порядка равны 1, мантисса не равна 0
Проблемы хранения вещественных чисел
Из-за ограниченного количества разрядов мантиссы возникают проблемы точности представления чисел.
Пример потери точности:
Число 0.110 в двоичной системе представляется как бесконечная периодическая дробь:
0.110 = 0.000110011001100110011…2
При сохранении в формате float (23 бита мантиссы) происходит обрыв и потеря точности.
Основные проблемы:
- Округление при преобразовании из десятичной в двоичную систему
- Потеря точности при выполнении арифметических операций
- Накопление ошибок при последовательных вычислениях
- Проблемы сравнения чисел из-за ошибок округления
Накопление ошибок при вычислениях
При выполнении последовательных операций с вещественными числами ошибки округления могут накапливаться, приводя к значительным погрешностям.
Пример накопления ошибки:
Вычисление суммы 1000000 раз числа 0.1:
сумма = 0.0
для i от 1 до 1000000:
сумма = сумма + 0.1
результат = сумма // Ожидается 100000.0, но будет небольшая погрешность
Как уменьшить накопление ошибок:
- Использовать тип данных с большей точностью (double вместо float)
- Избегать вычитания близких по величине чисел
- Минимизировать количество операций
- Использовать алгоритмы, устойчивые к ошибкам округления
Пример проблемы вычитания:
Вычисление \( y = \sqrt{x^2 + 1} — 1 \) при малых x
При x → 0,00… вычисление приводит к потере точности. Лучше использовать эквивалентное выражение:
\( y = \frac{x^2}{\sqrt{x^2 + 1} + 1} \)
Практические рекомендации
При работе с вещественными числами:
- Всегда помните о возможной потере точности
- Избегайте прямого сравнения на равенство (вместо \( a == b \) используйте \( |a — b| < \varepsilon \))
- Используйте подходящий тип данных в зависимости от требуемой точности
- Старайтесь избегать алгоритмов, усиливающих ошибки округления
Пример безопасного сравнения:
if (a == b) { … }
// Используйте:
epsilon = 1e-10; // Малая величина
if (abs(a — b) < epsilon) { ... }