Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Информационные преобразования числовых форматов....doc
Скачиваний:
3
Добавлен:
13.11.2018
Размер:
333.31 Кб
Скачать

Фиксированный вещественный формат

По отношению к компьютеру внешние устройства могут располагать информационные биты вещественных чисел по своему усмотрению, не затрачивая время на преобразования нормализации. Такая технология используется в контрольно-измерительных и управляющих устройствах, когда компьютер выполняет главные вычислительные действия и принимает решения по совокупности датчиков о воздействии на исполнительные органы машин и аппаратов. Тогда контроллеры и микропроцессоры внешних устройств подразумевают расположение разделяющей точки целой и дробной частей числа между фиксировано заданными битами. Например, если число имеет 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. Обратное преобразование floatfixed рассматривается позже в программе 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( ) завершена.