Внутреннее представление плавающих типов

Числа с плавающей точкой хранятся в памяти в экспоненциальной форме в двоичной системе счисления. Формула такого представления имеет вид

Внутреннее представление плавающих типов - student2.ru .

Здесь 1. Внутреннее представление плавающих типов - student2.ru – мантисса числа в двоичной системе, Внутреннее представление плавающих типов - student2.ru – порядок числа в двоичной системе.

Чтобы получить двоичные цифры мантиссы, нужно представить число в виде суммы степеней двойки. Например,

Внутреннее представление плавающих типов - student2.ru

Итак, для числа 5.3 мантиссаимеет вид:

Внутреннее представление плавающих типов - student2.ru = 01010011001100110011001100...2,

порядокравен:

Внутреннее представление плавающих типов - student2.ru = 102.

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

В памяти хранятся знак числа, часть мантиссы Внутреннее представление плавающих типов - student2.ru и порядок Внутреннее представление плавающих типов - student2.ru . Самая старшая единица мантиссы не хранится, но учитывается в вычислениях.

Рассмотрим для примера тип float, под который отводится 4 байта памяти с подряд идущими адресами. Из 32 бит, выделяемых для размещения float, старший 31-й разряд используется для хранения знака числа (0 – положительное число, 1 – отрицательное), в 8 разрядах (с 23-го по 30-й) хранится порядок и в 23-х разрядах (с 0-го по 22-й) размещается мантисса. Порядок хранится в увеличенном на шестнадцатеричное число 7F виде, то есть используется двоичная нотация с избытком 127. Это позволяет обойтись без специального разряда для хранения знака порядка.

Пусть для размещения числа типа float выделены байты с адресами

a, a+1, a+2, a+3.

Возможны различные способы размещения в этих байтах разрядов двоичного представления числа. В процессорах фирмы Intel принят способ

1234,

то есть младшие разряды двоичного представления числа размещаются в байтах с меньшими адресами. В табл.27. приведены примеры внутреннего представления чисел типа float.

Таблица 27. Двоичный код для чисел с типа float

Число Двоичный код 16 – ричный код
  порядок Мантисса
1.0 011 1111 1 000 0000 0000 0000 0000 0000 3f 80 00 00
2.0 100 0000 0 000 0000 0000 0000 0000 0000 40 00 00 00
10.0 100 0001 0 010 0000 0000 0000 0000 0000 41 20 00 00
5.30 100 0000 1 010 1001 1001 1001 1001 1010 40 A9 99 9A

13.8. Преобразование типов

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

f + i,

где f – число с плавающей точкой, i – целое.

Выражения, не имеющие смысла, не допускаются. Например, плавающее число нельзя использовать в качестве индекса массива.

Если возможна потеря информации, например, при присваивании целой переменной значения с плавающей точкой, компилятор может выдать предупреждение (warning), но такие выражения допустимы.

Тип char

Значения типа char – это просто малые целые, потому они свободно используются в арифметических выражениях. При вычислениях char предварительно преобразуется к целому типу. В качестве примера приведем функцию atoi, преобразующую строку цифр в ее числовой эквивалент.

// atoi: преобразование s в целое

int atoi(char s[])

{

int i, n = 0;

for(i = 0; s[i] >= ’0’ && s[i] <= ’9’; i++)

n = n*10 + s[i] – ’0’;

return n;

}

Выражение s[i] – ’0’ дает числовое значение цифры, размещенной в s[i], так как значения ’0’, ’1’,…, ’9’ образуют непрерывную возрастающую последовательность (’0’ = 48, ’1’ = 49,…, ’9’ = 57).

Предложенный вариант функции atoi несовершенен, например, не предусмотрена возможность записи числа в виде последовательности цифр, начинающейся знаком + или -. Заголовочный файл stdlib.h содержит описания ряда библиотечных функций для преобразования строк в числовые значения.

Функция

int atoi(const char *s)

переводит s в int, начальные пробелы игнорируются, число может иметь знак.

Функция

long atol(const char *s)

переводит s в long.

Функция

double atof(const char *s)

переводит s в double, игнорируя начальные пробелы.

Следующая функция lower преобразует заглавную латинскую букву в строчную. Если же символ не является заглавной буквой, он не изменяется.

int lower(int c)

{

if(c >= ’A’ && c <= ’Z’)

return c + ’a’ – ’A’;

else

return c;

}

Для латинских букв эта функция будет работать правильно, так как между одноименными буквами верхнего и нижнего регистров одинаковая разность, кроме того, латинский алфавит плотный, то есть между ’A’ и ’Z’ и между ’a’ и ’z’ расположены только буквы. Для русских букв в кодовой таблице 866, которая используется в DOS-программах, это не так. Заглавные русские буквы ’А’, ’Б’, …, ’Я’ идут плотно, а у строчных русских букв есть разрыв между ’п’ и ’р’, в котором расположены символы псевдографики. В кодовой таблице 1251, используемой в Windows, русские заглавные и строчные буквы расположены непрерывно в алфавитном порядке.

Имеются библиотечные функции для преобразования символов и проверки их типа, объявленные в заголовочном файле ctype.h.

Функция

int tolower(int c);

возвращает код малой (строчной) латинской буквы, соответствующей заглавной (прописной) латинская букве c. Если c не является заглавной латинской буквой, то возвращается c без преобразования.

Функция

int toupper(int c)

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

Функция

int isalpha(int c)

возвращает 1, если c – латинская буква, иначе 0.

Функция

int isdigit(int c)

возвращает 1, если c – цифра, иначе 0.

Функция

int isalnum(int c)

возвращает 1, если c – латинская буква или цифра, иначе 0.

Функция

int isspace(int c)

возвращает 1, если c – пробел, табуляция, новая строка, возврат каретки, новая страница, вертикальная табуляция, а иначе 0.

Функция

int isupper(int c)

возвращает 1, если c – заглавная латинская буква, иначе 0.

Перечисленные функции не обрабатывают правильно русские буквы.

Проверку

s[i] >= ’0’ && s[i] <= ’9’,

использованную в функции atoi, можно заметить на

isdigit(s[i]).

Язык не определяет, является тип char знаковым или нет, поэтому это зависит от реализации. Например, в C++Builder тип char считается знаковым. В Visual C++ тип char – беззнаковый. В Turbo C++ характеристика char определяется настройками компилятора. Для установки спецификации unsigned для char нужно выполнить команду меню Options, Compiler, Code generation и установить соответствующий флажок, рис.33.

Внутреннее представление плавающих типов - student2.ru

Рис.33. Настройки компилятора Turbo C++

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

Наши рекомендации