
- •Информационные преобразования числовых форматов
- •Позиционные системы счисления
- •Преобразования целых чисел в двоичной и десятичной системах счисления
- •Коды двоичных целых чисел
- •1. Знаковый прямой код целого числа.
- •2. Обратный код целого числа.
- •3. Дополнительный код целого числа.
- •Битовое отображение целого числа
- •Преобразования вещественных чисел в двоичной и десятичной системах счисления
- •Нормальная форма вещественного числа
- •Преобразование вещественного числа в целое число
- •Преобразование целого числа в вещественное число
- •Фиксированный вещественный формат
- •Символьные преобразования числовой информации
- •Список литературы
- •Оглавление
Фиксированный вещественный формат
По отношению к компьютеру внешние устройства могут располагать информационные биты вещественных чисел по своему усмотрению, не затрачивая время на преобразования нормализации. Такая технология используется в контрольно-измерительных и управляющих устройствах, когда компьютер выполняет главные вычислительные действия и принимает решения по совокупности датчиков о воздействии на исполнительные органы машин и аппаратов. Тогда контроллеры и микропроцессоры внешних устройств подразумевают расположение разделяющей точки целой и дробной частей числа между фиксировано заданными битами. Например, если число имеет 4 бита в дробной части, то точка подразумевается между битами 3 и 4 (рис. 3). По экономическим и производственным причинам процессор компьютера, как правило, не имеет специальных инструкций для выполнения арифметических действий с фиксированными вещественными числами. В такой ситуации необходимы программы, позволяющие преобразовывать вещественные числа из фиксированного формата в нормализованный формат и наоборот.
11 |
10 |
9 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
1 |
0 |
0 |
0 |
0 |
1 |
1 |
0 |
0 |
1 |
0 |
0 |
Целая часть
Дробная часть
Знак числа
Разделяющая дробная точка
Рис. 3. Фиксированное 12-битное расположение вещественного числа -6.25 в
прямом коде. Положение дробной точки подразумевается между битами 3 и 4.
Шестнадцатеричный код числа 0x864 = -6.25.
Ниже представлена программа C5, в которой функция FixedFloat( ) преобразует вещественное число из фиксированного формата с разделяющей точкой между битами 3 и 4 в нормализованный формат мантиссы и порядка типа float. Обратное преобразование float – fixed рассматривается позже в программе C6.
// Program C5
// Преобразование fixed - float
#include <stdio.h> // printf
#include <conio.h> // getch
#include "BinaryInt.h" // BinaryInt
#include "BinaryFloat.h" // BinaryFloat
typedef unsigned int DWORD; // синоним целого типа
float FixedFloat( DWORD x, DWORD size, DWORD r )
{ if( ( x << ( 32 - (size-1) ) ) == 0 ) return 0.0;
DWORD b = 1 << ( size - 2 ); // бит начала числа
BinaryInt( "b = ", b ); // бинарный вид
DWORD s = b << 1; // 1 напротив знака числа
BinaryInt( "s = ", s ); // бинарный вид
int i; // позиция старшей единицы в числе
for( i = size - 2; i >= 0; i-- ) // цикл позиций
{ if( x & b ) break; // позиция старшей единицы
b >>= 1; // сдвиг 1 в соседний бит справа
}
printf( "\ni = %d", i ); // монитор
int p = i - r; // математический порядок - 1
printf( "\np = %d", p ); // монитор
DWORD t = p + 127; // порядок в стиле Intel
BinaryInt( "t = ", t ); // бинарный вид порядка
DWORD m = x << ( 32 - i ) >> 9; // мантисса Intel
BinaryInt( "m = ", m ); // бинарный вид мантиссы
m |= t << 23; // модуль вещественного числа
BinaryInt( "m = ", m);//бинарный вид модуля числа
if( x & s ) m |= 0x80000000; // знак числа
BinaryInt( "m = ", m );// бинарный вид результата
union
{ DWORD d; // поле целого типа
float f; // поле вещественного типа
} u;
u.d = m;
return u.f; // вернуть результат
}
//---------------------------------------------------
void main ( void )
{ unsigned int x; // фиксированная переменная
printf( "x = " ); scanf( "%x", &x );// ввод числа
BinaryInt( "x = ", x ); // бинарный вид числа
float f = FixedFloat( x, 12, 4);// преобразование
printf( "\nf = %f", f ); // монитор
BinaryFloat( "f = ", f ); // бинарный вид числа
getch(); // просмотр результата
}
Если во время выполнения программы C5 ввести шестнадцатеричное число 864, которое в фиксированном вещественном формате с дробной частью 4 бита соответствует десятичному числу -6.25 (рис. 3), то следующая информация появляется на мониторе.
x = 864
x = 00000000000000000000100001100100
b = 00000000000000000000010000000000
s = 00000000000000000000100000000000
I = 6
p = 2
t = 00000000000000000000000010000001
m = 00000000010010000000000000000000
m = 01000000110010000000000000000000
m = 11000000110010000000000000000000
f = -6.25
f = 11000000110010000000000000000000
Функция FixedFloat( ) возвращает число типа float и выполняет преобразование вещественного числа из фиксированного формата в формат типа float. Конструкция объявления параметров содержит число в фиксированном формате DWORD x, общее количество бит в фиксированном формате DWORD size, количество бит в дробной части DWORD r. В теле функции FixedFloat( ) выполняется проверка на 0 исходного числа if( ( x << ( 32 - ( size-1 ) ) ) == 0 ) return 0.0.
Переменная DWORD b = 1 << ( size - 2 ) устанавливает 1 в бите, с которого начинается беззнаковая часть числа. В нашем примере – это бит 10. Бинарный вид переменной b выводится на монитор BinaryInt( "b = ", b ). В дальнейшем потребуется переменная DWORD s = b << 1, которая содержит 1 напротив знака исходного числа. Изображение s появляется на мониторе BinaryInt( "s = ", s ).
Следующая часть алгоритма определяет номер бита, в котором расположена старшая 1 вещественного числа. Для этого используется переменная int i. Необходимые действия выполняются под управлением заголовка цикла for( i = size - 2; i >= 0; i-- ), который руководит просмотром бит числа, начиная с послезнаковой позиции size – 2. На каждой итерации значение i уменьшается на 1, что соответствует просмотру очередного бита справа. В теле цикла осуществляется проверка, что содержит бит с номером i. Если в бите i находится 1, то позиция старшего бита исходного числа найдена, и цикл следует прекратить if( x & b ) break. В противном случае в бите i находится 0. Тогда необходимо сдвинуть 1 влево в переменной b >>= 1 и выполнить следующую итерацию цикла. После окончания цикла в переменной i находится номер бита со старшей единицей исходного числа. Для контроля значение i выводится на монитор printf( "\ni = %d", i ).
Уменьшенный на единицу математический порядок числа получается после вычитания размера дробной части int p = i – r. Значение p отображается на мониторе printf( "\np = %d", p ). Компьютерное представление порядка вычисляется как unsigned int t = p + 127. Бинарный вид порядка выводится на монитор BinaryInt( "t = ", t ).
Знание порядка позволяет оформить мантиссу со спрятанной единицей DWORD m = x << ( 32 - i ) >> 9. Ее можно посмотреть на мониторе BinaryInt( "m = ", m ). Остается присоединить спереди порядок m |= t << 23. Модуль числа готов BinaryInt( "m = ", m ). Знак исходного числа переносится в нормализованный формат if( x & s ) m |= 0x80000000 с последующим выводом на монитор BinaryInt( "m = ", m ).
Чтобы вернуть результат, создается объект объединения u. В его поле u.d = m загружается преобразованное нормализованное число. Поле u.f возвращается как результат выполнения функции return u.f. Функция FixedFloat( ) завершена.
Ниже представлена программа C6, в которой функция FloatFixed( ) выполняет преобразование нормализованного вещественного числа типа float в число фиксированного формата с дробной точкой между битами 3 и 4 (рис. 3).
// Program C6
// Преобразование float - fixed
#include <stdio.h> // printf
#include <conio.h> // getch
#include "BinaryInt.h" // BinaryInt
#include "BinaryFloat.h" // BinaryFloat
typedef unsigned int DWORD; // синоним целого типа
DWORD FloatFixed( float ff, DWORD size, DWORD r )
{ union
{ DWORD n; // поле целого типа
float f; // поле вещественного типа
} u; // объект объединения
u.f = ff; // загрузить число в объединение
if( ( u.n << 1 ) == 0 ) return 0; // число 0
DWORD t = (u.n & 0x7F800000) >>23;//порядок Intel
BinaryInt( "t = ", t ); // бинарный вид порядка
int p = t - 127; // математический порядок - 1
printf( "\np = %d", p ); // монитор
DWORD m = ( ( u.n << 8 ) | 0x80000000);//мантисса
DWORD z = m >> ( 31 – p -r);//фиксированное число
BinaryInt( "z = ", z);//бинарный вид модуля числа
z |= ( u.n & 0x80000000 ) >> ( 31 - ( size-1 ) );
BinaryInt( "z = ", z );// бинарный вид результата
return z; // вернуть фиксированное число
}
//---------------------------------------------------
void main ( void )
{ float f; // образец результата
printf( "f = " ); scanf( "%f", &f );// ввод числа
BinaryFloat( "f = ", f ); // бинарный вид образца
unsigned int x = FloatFixed( f, 12, 4 );
printf( "\nx = %x", x ); // шестнадцатеричный вид
BinaryInt( "x = ", x );// бинарный вид результата
getch(); // просмотр результата
}
Если после запуска программы C6 ввести число -6.25, то следующий результат появляется на мониторе.
f = -6.25
t = 00000000000000000000000010000001
p = 2
z = 00000000000000000000000001100100
z = 00000000000000000000010001100100
x = 864
x = 00000000000000000000010001100100
Функция FloatFixed( ) осуществляет преобразование вещественного числа типа float в число с фиксированной точкой. Конструкция объявления параметров содержит значение поступающего числа float ff, общее количество бит в результирующем числе DWORD size и количество бит в дробной части DWORD r. В теле функции FloatFixed( ) используется объект объединения u для последующего выполнения битовых инструкций. Исходное число копируется в этот объект u.f = ff с проверкой на нулевое значение if( ( u.n << 1 ) == 0 ) return 0.
Алгоритм преобразования начинается с определения порядка нормализации, который можно выделить с помощью битовых операций DWORD t = ( u.n & 0x7F800000) >> 23 и посмотреть на мониторе BinaryInt( "t = ", t ). Математический порядок на 1 меньше получается как int p = t – 127 с визуальным контролем printf( "\np = %d", p ).
Затем восстанавливается спрятанная 1 мантиссы DWORD m = ( ( u.n << 8 ) | 0x80000000 ). Мантисса сдвигается вправо с учетом порядка и размера дробной части числа DWORD z = m >> ( 31 - p - r ) с последующим отображением на мониторе BinaryInt( "z = ", z ). Осталось поместить знак числа z |= ( u.n & 0x80000000 ) >> ( 31 - ( size - 1 ) ); BinaryInt( "z = ", z ), и вернуть результат return z. Функция FloatFixed( ) завершена.