Страницы

Представления вещественных чисел в формате с фиксированной точкой

Ранее мы рассмотрели подробно, как представляются целые числа (integer) в процессорах. Для представления вещественных (real) чисел в компьютерных системах применяются формат чисел с плавающей запятой (float-point) и формат чисел с фиксированной запятой (fixed-point). Формат fixed-point также называется fractional.

Для представления вещественного числа в формате числа с плавающей запятой используют отдельные биты для кодирования знака, мантиссы и порядка.

При представления чисел с фиксированной запятой порядок не сохраняется, а "держится в уме". То есть для восстановления вещественного числа недостаточно знать все биты сохраненного числа, нужно еще "помнить" и порядок числа

Существуют различные форматы кодирования знака, мантиссы и порядка, но общеупотребимым на данный момент является формат IEEE-754, который и реализован в большинстве компьютерных систем. Этот формат описывает два варианта кодирование - с одинарной и двойной точностью. В терминах языков С/С++/Java это типы float и double. Тип float - это 32 битное число, тип double - это 64 битное число.

Термины, которые будут использоваться далее

  • Целые числа (integer) — положительные и отрицательные числа без дробной части

  • Вещественные числа (real) — положительные и отрицательные числа числа с дробной частью

  • Вещественные числа в формате с плавающей точкой (float-point) — компьютерное представление вещественных чисел, где используются отдельные биты для кодирования знака, мантиссы и порядка.

  • Вещественные числа в формате с фиксированной точкой (fixed-point или fractional) — компьютерное представление вещественных чисел, где сохраняется мантисса, а порядок "держится в уме"

  • float — компьютерный формат представления вещественных чисел с плавающей точкой по стандарту IEEE-754. Требует 32 бита (4 байта) для каждого числа

  • double — компьютерный формат представления вещественных чисел с плавающей точкой по стандарту IEEE-754. Требует 64 бита (8 байт) для каждого числа

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

Представление вещественных чисел с фиксированной запятой

При представления числа с фиксированной запятой необходимо выбрать количество бит для представления целой и дробной частей. Общее количество бит (b) удобно привязать к размеру переменной целого типа (integer). Это может быть 8, 16, 24 или другое значение. Выбрав после этого количество бит для целой части мы получим количество бит для дробной части, как разницу между общим количеством бит переменной целого типа и количеством бит для целой части. Такой формат представление принято записывать в виде Qm.n, где m — это количество бит целой части, а n — количество бит дробной части.

Формат данных (Qm.n)
Общее количество бит (b)
Количество бит для целой части (m)
Количество бит для дробной части (n)

Максимальное и минимальное значения

При вычислениях важно помнить минимальное и максимальное значения, которые могут сохраняться в регистрах и использоваться при операциях.

  • INT_MAX — это максимальное целое число со знаком, равное 2b−1−1 (например при b=16 — это будет 216−1−1=32767 или 7fff16)

  • INT_MIN — это минимальное целое число со знаком, равное 2b−1 (например при b=16 — это будет 216−1=-32768 или 800016)

  • UINT_MAX — это максимальное беззнаковое целое число, равное 2b−1 (например при b=16 — это будет 216−1=65535 или ffff16)

Максимальные/минимальные значения
Формат INT_MAX INT_MIN UINT_MAX
Fractional16
Fractional10

После выбора количества бит отведенных на все число и количества бит отведенных для целой части мы сможем произвести конвертацию и определить минимальное и максимальное возможное число для этого представления.

Конвертация из Float-Point в Fixed-Point (Fractional)

Для конвертации вещественного числа в формате float-point необхожимо умножить исходное число на 2n−1. Подробная реализации такого умножения состоит из нескольких действий.

  • Умножить исходное вещественное число на 2n−1 (например при n=15 — это будет 215−1=32767)
  • Округлить до целого числа. (Округление выполняется прибавлением 0.5 и отбрасыванием дробной части)
  • Проверить не вышел ли результат за пределы допустимых значений
  • Преобразовать в integer
Конвертация Float-Point во Fractional
Произвольное Минимум Максимум
Float-Point
Fractional16

Конвертация из Fractional во Float-Point

Для обратной конвертации (из fractional во float-point) необходимы следующие действия

  • Преобразовать исходное число из integer во float (или double)
  • Разделить его на 2n (например при n=15 — это будет 215=32768)
Обратная конвертация
Float-Point

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