![](/user_photo/_userpic.png)
Программные преобразования числовой информации (96
..pdfBinaryInt('f=',g.n,32); p:= g.n Shr 23; BinaryInt('p=',p,8); t:= p -127; BinaryInt('t=',t,8);
If t<0 Then begin
Result:=0;
Exit;
end;
z:=((g.n Shl 8) or $80000000) Shr (31-t);
If g.n and $80000000 <> 0 Then z:= not z + 1; BinaryInt('z=',z,32);
Result:=z;
end;
var f :single; n :integer;
begin
Write (‘f=’); Readln (x); n:=FloatInt (f); Writeln ('n= ',n); Readln;
end.
Если в качестве исходного ввести число 6,25, то на мониторе появляются следующие строки:
f = 6.25
f = 01000000110010000000000000000000 p = 10000001
t = 00000010
z = 00000000000000000000000000000110 n = 6
В этом мониторном протоколе действий переменная p содержит «смещенный» порядок хранимой мантиссы, определяемый в результате сдвига исходного бинарного числа вправо на 23 бита. Истинный порядок t получается после вычитания из значения p смещения 27-1, поэтому t имеет тип integer, пригодный для
21
положительных и отрицательных значений. Это число 00000102 = = 210 показывает положение воображаемой дробной разделительной точки, т. е. хранимая мантисса 1001 ≈ 10,01. Результат запоминается в переменной z = 1102 = 610. Эти действия последовательно запрограммированы в функции FloatInt() в программе
Prog2.
Взаимодействие с отрицательными порядками проявляется с другими числами, например 0,25. На мониторе получается следующий результат:
f = 0.25
f = 00111110100000000000000000000000 p = 01111101
t = 11111110 n = 0
Впримере с числом 0,25 порядок отрицательный: p = 01111101.
Врезультате смещения получаем t < 0, целая часть равна 0.
Алгоритм функции FloatInt() успешно работает с числом, у которого целая часть равна 1. Выполняя программу Prog2 для сходного числа, например 1,25, получаем следующие строки на мониторе:
f = 1.25
f = 00111111101000000000000000000000 p = 01111111
t = 00000000
z = 00000000000000000000000000000001 n = 1
8. МОДЕЛИРОВАНИЕ ПРЕОБРАЗОВАНИЯ integer – single
Пусть исходное число находится в четырехбайтном формате типа integer. Необходимо преобразовать это число в четырехбайтный формат типа single. Для этого потребуется смоделировать мантиссу и порядок нормализованного числа в таком виде, какой принят для хранения вещественных чисел (с учетом «спря-
22
танной» единицы мантиссы). В языке Паскаль подобное преобразование выполняется автоматически:
Var f:single; n:integer;
Begin f:=n;
end;
Однако такое решение подразумевает выполнение функции преобразования из типа integer в тип single, т. е. мы должны решить задачу, обратную задаче программы Prog2. Программа Prog3 моделирует подобное преобразование:
program Prog3;
Function IntFloat(n:integer):Single; Var
b,m,k:cardinal;
i,p:byte;
g:rCardSingl; begin
BinaryInt('n=',n,8);
If n and $80000000 <> 0 Then k:= not n + 1 Else k:=n;
If k=0 Then begin
Result:=0.0;
Exit;
end; b:= $80000000; i:=31;
While k and b = 0 Do begin
i:=i-1; b:=b Shr 1;
end;
Writeln('i=',i); p:= i+127; Writeln('p=',p);
23
BinaryInt('p=',p,8); m:=k Shl (32-i) Shr 9; BinaryInt('m=',m,32); g.n:=m or (p Shl 23);
g.n:= g.n or (n and $80000000); BinaryInt('f=',g.n,32); Result:= g.f;
end; var
n:integer; begin
Write('n='); Readln(n); Writeln('f= ',IntFloat(n):8:6); Readln;
end.
Если в начале выполнения программы Prog3 ввести число n = 6, то последовательность преобразований появится на мониторе в следующем виде:
n = 6
n = 00000000000000000000000000000110 i = 2
p = 129
p = 10000001
m = 00000000010000000000000000000000 f = 01000000110000000000000000000000 f = 6.000000
Интересен результат, получающийся после ввода числа –1:
n = -1
n = 11111111111111111111111111111111 i = 0
p = 127
p = 01111111
m = 00000000000000000000000000000000 f = 10111111100000000000000000000000 f = -1.000000
24
![](/html/65386/468/html_BQJkksh6QO.mWnE/htmlconvd-oo8Df525x1.jpg)
Алгоритмы программы Prog3 и функции IntFloat( ) настолько очевидны, что их анализ предлагаем читателю провести самостоятельно.
9. ПРЕОБРАЗОВАНИЕ ЧИСЛА ИЗ ФИКСИРОВАННОГО ВЕЩЕСТВЕННОГО ФОРМАТА В ЧИСЛО ТИПА single
Задачи на преобразование форматов чисел с фиксированным разделением целой и дробной частей часто возникают при работе с информацией, поступающей от различных датчиков, тарификация которых предполагает наличие вещественных чисел с заданной точностью. Минимальная требуемая точность значащих цифр – 12-битная. В каждом конкретном приложении где-нибудь фиксируется воображаемая точка, разделяющая целую и дробную части. В качестве примера допустим, что информация располагается в битах 0 – 11. Младшие значения находятся в младших битах. Бит 11 хранит знак числа: 0 – для положительного числа и 1 – для отрицательного числа. Информация представлена в прямом коде. Чтобы не очень усложнять задачу, будем считать, что подразумеваемая разделяющая точка может находиться в любом месте между битами 0 и 10. Например, не занимающая специального бита точка предполагается между битами 3 и 4 (рис. 7).
11 |
|
10 |
9 |
8 |
7 |
6 |
5 |
4 |
|
|
3 |
2 |
1 |
0 |
|
||||||
1 |
|
0 |
0 |
0 |
0 |
|
1 |
|
1 |
0 |
|
|
0 |
1 |
|
0 |
0 |
|
|||
|
|
|
|
|
|
|
|
Целая часть |
|
|
|
|
|
Дробная |
|
|
|||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
часть |
|
|
|||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Разделяющая дробная точка |
|
|
|||||||||
Знак числа |
|
|
|
|
|
|
|
||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Рис. 7. Фиксированное 12-битное расположение вещественного числа – 6,25; положение дробной точки подразумевается между битами 3 и 4; шестнадцатеричный код числа – 6,25. = $864
В программе Prog4 функция FixedFloat() осуществляет преобразование из фиксированного формата представления вещественного числа в нормализованный формат типа single:
25
program Prog4; Type
rCardSingl = Record Case Byte of
0:(n:cardinal);
1:(f:single);
end;
Function FixedFloat(x:cardinal;size:byte;point:byte):Single;
var b,n,bs,m1,t:cardinal; i,r:byte; p,pn:shortint; g:rCardSingl;
begin
If x=0 Then begin
Result:=0.0;
Exit;
end;
Writeln(‘size=’,size);
Writeln(‘point=’,point);
BinaryInt('x=',x,32);
n:=x;
BinaryInt('n=',n,32);
bs:=1;
For i:=0 To size-2 Do bs := bs shl 1;
b := bs shr 1; i := size-2;
While (i>0) and (n and b = 0) Do begin
b := b shr 1; i := i - 1;
end;
pn := i - point; Writeln('pn= ',pn);
m1 := (n shl (32-(pn+point))) shr 9; BinaryInt('m1=',m1,32);
p := pn - 1;
If p >= 1 Then r := (p-1) or $80
26
Else If p=0 Then r := $7F Else r:= (p-1) and $7F;
BinaryInt('r=',r,8); t := r shl 23; BinaryInt('t=',t,32); g.w := t or m1;
If (x and bs) <> 0 Then g.w := g.w or $80000000; BinaryInt('f=',g.w,32);
Result:= g.f; end;
begin
x:= $864; WriteHex('x=',x);
Writeln('f= ',FixedFloat(x,12,3):9:6); Readln ;
End.
В основной программе число с фиксированной точкой вводится в 16-м формате. Например, если число занимает 12 бит и дробная точка находится между битами 3 и 4, то число – 6,2510 кодируется как 86416. Для этого случая на мониторе появляются следующие строки:
x = |
$864 |
size |
= 12 |
point = 3 |
|
x = |
00000000000000000000100001100100 |
n = |
00000000000000000000100001100100 |
pn= |
3 |
m1= |
00000000010010000000000000000000 |
r = |
10000001 |
t = |
01000000100000000000000000000000 |
f = |
01000000110010000000000000000000 |
f = |
11000000111010000000000000000000 |
f = |
-6.250000 |
Для фиксированного числа –1,2510 соответствующий код 81416 сопровождается следующей информацией на мониторе:
x = $814 size = 12
27
point = 3
x = 00000000000000000000100000010100 n = 00000000000000000000100000010100 pn= 1
m1= 00000000001000000000000000000000 r = 01111111
t = 00111111100000000000000000000000 f = 00111111101000000000000000000000 f = 10111111101000000000000000000000 f = -1.250000
Еще одно испытание необходимо провести для числа с нулевой целой частью, например – 0,2510 ≈ 80416:
x = |
$804 |
size |
= 12 |
point = 3 |
|
x = |
00000000000000000000100000000100 |
n = |
00000000000000000000100000000100 |
pn= |
-1 |
m1= |
00000000000000000000000000000000 |
r = |
01111101 |
t = |
00111110100000000000000000000000 |
f = |
00111110100000000000000000000000 |
f = |
10111110100000000000000000000000 |
f = |
-0.250000 |
Впрограмме Prog4 функция FixedFloat() построена по тем же принципам, что и функция IntFloat() из программы Prog3. В функции FixedFloat() параметрами являются: исходное фиксированное число x, размер числа в битах size, положение дробной точки слева от бита c номером point.
Втеле функции FixedFloat() проводится проверка элементарной нулевой ситуации и делаются контрольные распечатки BinaryInt(,x = ,, x, 32); для визуального контроля на мониторе.
Первым шагом алгоритма является поиск знакового бита ис-
ходного числа по значению параметра size. Для этого единица
28
устанавливается в бит 0 переменной bs = 1;. Далее с помощью инструкции цикла единица сдвигается влево в знаковый бит i;
For i:=0 To size-2 Do bs := bs shl 1;
Номер старшего бита b исходного числа находится на 1 бит справа от бита знака:
b := bs shr 1;.
На втором шаге определяется истинный порядок целой части исходного числа, исходя из положения десятичной точки:
i := size-2; // номер бита While (i>0) and (n and b = 0) Do
begin
b := b shr 1; // сдвинуть 1 в соседний бит
справа
i := i - 1; end;
pn := i - point; // порядок числа
На третьем шаге формируется мантисса хранения, которая, напомним, «прячет» старшую единицу исходной мантиссы. Делается это с помощью сдвигов, сначала влево с потерей старшей единицы, а потом вправо на 9 бит на точное место мантиссы сохранения:
m1 := (n shl (32-(pn+point))) shr 9;
На четвертом шаге формируется порядок сохранения r, который сдвигается влево на точное место t своего расположения:
p = pn |
- 1; |
|
// порядок сохранения |
||
If p >= 1 Then r := (p-1) or $80 |
// для |
||||
чисел > 1 |
|
|
|
// порядок для 1 |
|
Else If p=0 Then r := $7F |
|||||
Else r:= |
(p-1) and $7F; |
// |
порядок для < 1 |
||
t := r |
shl 23; |
// порядок |
хранения мантиссы |
29
На пятом шаге оформляется положительный вариант числа в результате битовой дизъюнкции порядка и мантиссы сохранения в поле объединения результата:
g.n := t or m1; |
// положительное веще- |
ственное число |
|
Шестой шаг учитывает знак отрицательного исходного числа. Для этого проверяется знаковый бит фиксированного числа. Если он установлен в единицу, то выходное число получает 1 в бите 31:
If (x and bs) <> 0 |
// отрицательное число |
|
Then g.n := g.n or |
$80000000; |
// 1 в бите 31 |
Алгоритм преобразования закончен. Результат возвращается в виде типа single.
10.ПРЕОБРАЗОВАНИЕ ЧИСЛА ТИПА single В ЧИСЛО
СФИКСИРОВАННЫМ ВЕЩЕСТВЕННЫМ ФОРМАТОМ
Вчислах с фиксированным вещественным форматом точка между целой и дробной частями не занимает отдельного бита (рис. 7), что используется в технических системах с управляющим компьютером, который посылает числовой результат вычисления на исполнение в периферийное оборудование. Для примера допустим, что число занимает 12 бит в прямом коде. Знак числа находится в бите 11. Дробная точка задается в пределах от бита 0 до бита 11. Эта задача является «обратной» к задаче в программе
Prog4. В программе Prog5 функция FloatFixed( ) выполняет требуемые действия:
program Prog5; Type
rCardSingl = Record Case Byte of
0:(n:cardinal);
1:(f:single);
end;
Procedure HexInt (n:cardinal;var s:string);
30