Поможем написать учебную работу
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.

Предоплата всего

Подписываем
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.
Предоплата всего
Подписываем
Лабораторная работа №4.
«Моделирование процессов преобразования информации в сопроцессоре».
Арифметический сопроцессор (FPU) – устройство, непосредственно подключенное к центральному процессору (CPU) Intel и предназначенное для выполнения операций над числами в формате с плавающей точкой (вещественные числа) и длинными целыми числами.
Арифметический сопроцессор значительно (в десятки раз) ускоряет вычисления, связанные с вещественными числами. Он может вычислять такие функции как синус, косинус, логарифмы и т.д.
Очень важно понимать, как работает сопроцессор. Также очень важно понимать форматы его данных.
Данных сопроцессора храняться в 8-ми регистрах (ST0-ST7) во внутреннем формате (long double для C/C++, extended для Pascal). Прикладные программы читают эти данные из регистров и корректно декодируют.
Аналогичным процессам и посвящена данная лабораторная работа.
ОСНОВНЫЕ СВЕДЕНИЯ.
Прежде чем говорить о форматах вещественных чисел, используемых сопроцессором, вспомним о числах с плавающей точкой, встречающихся в научных расчетах. В общем виде эти числа можно записать следующим образом:
(знак)(мантисса)*10(знак)(порядок)
Например: -1.35*10-5
Здесь знак – это минус (унарный плюс недопустим!), мантисса – 1.35, порядок - -5. Как видите, порядок тоже может иметь знак. Вспомним также такое понятие, как нормализованное представление чисел:
если целая часть мантиссы числа состоит из одной, не равной нулю цифры, то число с плавающей точкой называется нормализованным.
Преимущество использования нормализованных чисел состоит в том, что для фиксированной разрядной сетки числа (для фиксированного количества цифр в числе) такие числа имеют наибольшую точность. Кроме того, нормализованное представление исключает неоднозначность – каждое число с плавающей точкой может быть представлено различными (ненормализованными) способами:
123.5678*105 = 12.35678*106 = 1.235678*107 = 0.1235678*108
Для тех, кто программировал на языках высокого уровня должно быть знакомо следующее представление чисел с плавающей точкой:
(знак)(мантисса)Е(знак)(порядок).
Например, -5.35Е-2 означает число –5.35*10-2. Такое представление называется научной нотацией.
Сопроцессор фирмы Intel может работать с вещественными числами в трех форматах:
· одинарной точности
· двойной точности
· расширенной точности
или
· float
· double
· long double
для языка C/C++
· single
· double
· extended
для Pascal/Delphi
Следует отметить, что тип real не поддерживается сопроцессором и его использование в программах нежелательно ввиду потерь времени на преобразование информации к форматам, поддерживаемым сопроцессором и обратно.
Числа в формате данных сопроцессора занимают соответственно 4, 8 и 10 байтов:
1 бит 8 бит 23 бита
1 бит 11 бит 52 бита
1 бит 15 бит 64 бита
На рисунке приведены числа одинарной, двойной и расширенной точности соответственно.
В любом представлении старший бит «Зн» определяет знак вещественного числа:
0 – положительное число
1 – отрицательное число
Обратите внимание: в отличие от целых чисел, вещественные представляются в прямом коде.
Все равные по абсолютному значению положительные и отрицательные числа отличаются только этим битом. В остальном числа с равным знаком полностью симметричны.
Арифметический сопроцессор работает с нормализованными числами, поэтому поле мантиссы содержит мантиссу нормализованного числа.
Здесь используется двоичное представление чисел. Сформулируем определение нормализованного числа для этого случая:
если целая часть мантиссы числа в двоичном представлении равна 1, то число с плавающей точкой называется нормализованным.
Так как для нормализованного двоичного числа целая часть всегда равна единице, то эту единицу можно не хранить. Именно так и поступили разработчики сопроцессора – в форматах одинарной и двойной точности числа целая часть мантиссы не хранится. Таким образом экономится один бит памяти.
Для наглядности представим мантиссу числа в такой форме:
n.nnnnnn…n
Здесь символом ‘n’ обозначается либо 0, либо 1. Нормализованные числа в крайней левой позиции содержат 1, поэтому их можно представить в виде:
1.nnnnnn…n
Представление с расширенной точностью используется сопроцессором для выполнения всех операций. И даже более того, все операции с числами сопроцессор выполняет только над числами в формате с расширенной точностью. В этом формате хранится и лишний бит целой части нормализованного числа.
Основная причина использования для вычислений чисел с расширенной точностью – предохранение программы от возможной потери данных, связанной с погрешностью округления и конечностью разрядной сетки.
Поле порядка – это степень двойки, на которую умножается мантисса, плюс смещение, равное 127 для одинарной точности, 1023 для двойной, 16383 для расширенной.
Для того, чтобы определить абсолютное значение числа с плавающей точкой, можно воспользоваться следующими формулами:
· одинарная точность: 1.(цифры мантиссы)*2(Р-127)
· двойная точность: 1.(цифры мантиссы)*2(Р-1023)
· расширенная точность: 1.(цифры мантиссы)*2(Р-16383)
Знак числа, как уже говорилось, определяется старшим битом.
Приведем конкретный пример. Пусть мы имеем число с одинарной точностью, которое в двоичном виде выглядит так:
1 01111110 11000000000000000000000
Для этого числа знак равен 1 (отрицательное число), порядок – 126, мантисса – 11 (в двоичной системе счисления, то есть 0.11 в двоичном виде или 2-1 + 2-2 = 0.5+0.25+0.75 в десятичном). С учетом целой части, это число равно:
-1.11*2(126-127) = - (2+0.5+0.25) * 2-1 = -1.75*0.5= -0.875
Вообще, двоичная мантисса вида 1.nnnnnnnnnn означает следующее:
2 + n*2-1+n*2-2+…+n*2-k
Следует учесть, что не все десятичные числа могут быть разложены в конечный ряд по степеням двойки, например 0.1
ЗАДАНИЕ НА ЛАБОРАТОРНУЮ РАБОТУ.
Необходимо реализовать программу, выполняющую конверсию введенного с клавиатуры десятичного числа с плавающей точкой в формат сопроцессора и обратное преобразование (вводится двоичное представление, программа выдает соответствующее десятичное число). Ввод осуществляется с клавиатуры, вывод на экран.
Программа должна поддерживать все три типа данных сопроцессора.
В программе должна присутствовать проверка правильности конверсии путем сравнения с реальным представлением числа в сопроцессоре, например:
program chek;
a : extended;
b : array [1..10] of byte absolute a;
begin
for i:=1 to 10 do
dec2bin(a[i]);
endfor
end;
program dec2bin(a:byte);
begin
for i:=1 to 8 do
write(a mod 2);
a:=a div 2;
end;
end;
В виду сложности ввода и понимания большого количества нулей и единиц в программе должен быть предусмотрен раздельный ввод и вывод порядка, знака, мантиссы, причем вывод должен осуществляться в двоичном, десятичном и шестнадцатеричном виде.
Пример внешнего вида программы:
Введите число: -0.875
|
|||||
Знак: 1
|
Порядок: 01111110 (126d, 7E)
|
Мантисса: 11000000000000000000000 (0.75d, 0.44h)
|
Решение.
#include <iostream>
#include <memory>
#include <math.h>
#include <vector>
#include <conio.h>
#include <algorithm>
#include <string>
using namespace std;
typedef unsigned char byte;
void float2bin(float, byte *, const int = 32);
void double2bin(double, byte*, const int = 64);
void longdouble2bin(long double, byte*, const int = 80);
bool check_float(float, byte* , const int = 32);
bool check_double(double, byte*, const int = 64);
//проверка 80битного представления числа нет, поскольку компиляторы MS VC++ и gcc не поддерживают 80битные long double
//в MS VC++ long double = double, в gcc 12 байт(96 бит)
void print_binary(byte*, const int);
void bit4_bin2hex(vector<byte>&);
void print_binary(byte*, const int);
int bin2integer_part(vector<byte>&);
void integer_part2bin(int, vector<byte>&);
//функции обратного преобразования
float bin2float(byte* , const int );
double bin2double(byte* , const int );
long double bin2longdouble(byte* , const int );
template <class T>
void real_part2bin(T number, vector<byte>& binout, int digits)
{
if(number == 0.0)
return;
for(int i = 0; i < digits && number != 0.0; i++)
{
number *= 2;
if(number >= 1)
{
binout.push_back(1);
number -= 1.0;
}
else
binout.push_back(0);
}
}
template <class T>
T bin2real_part(vector<byte>& binary)
{
T number = 0;
for(int i = 0; i < (int)binary.size() ; i++)
{
number += pow(2.0, -1*(i + 1)) * (T)binary[(int)binary.size() - i - 1 ];
}
return number;
}
//функция для ввода массива 0 и 1 в вектор байт
void input_vector_bin(vector<byte>&, const int);
//интерфейсы
bool input_binary_interface(byte*, const int);
void work_with_binary();
void work_with_float_numbers();
int main()
{
setlocale(0, "Russian");
int select;
do{
cout << "Машинное представление вещественных чисел" <<endl;
cout << "1 - преобразование десятичных вещественных чисел в формат сопроцессора"<<endl;
cout << "2 - преобразование двоичного машинного представления в десятичное исчисление"<<endl;
cin >>select;
}while(select != 1 && select !=2);
if( select == 1)
work_with_float_numbers();
else
work_with_binary();
_getch();
}
void float2bin(float number, byte *bin, const int arr_size )
{
const int count_poryadok = 8;
const int count_mantissa = 23;
const int add_por = 127;
memset(bin, 0, sizeof(byte)*arr_size);
if(number == 0.0)
{
return;
}
if(number < 0)
bin[arr_size - 1] = 1;
number = fabs(number);
int offset = 0;
vector<byte> real_part_bin;
vector<byte> poryadok;
if(number >= 1.0)
{
int int_part = (int)number;
vector<byte> int_part_bin;
integer_part2bin(int_part, int_part_bin);
offset += int_part_bin.size() - 1;
int por = add_por + offset;
integer_part2bin(por, poryadok);
copy(poryadok.begin(), poryadok.end(), bin + count_mantissa);
copy(int_part_bin.begin(), int_part_bin.end() - 1, bin + (count_mantissa - offset));
number -= (int) number;
real_part2bin(number, real_part_bin, count_mantissa - offset);//и его двоичное представление
reverse(real_part_bin.begin(), real_part_bin.end()); //полученное представление записываем в обратном порядке
copy(real_part_bin.begin(), real_part_bin.end(), bin + (count_mantissa - offset - (int)real_part_bin.size()));
}
else //если целой части нет
{
const int size = add_por;
real_part2bin(number, real_part_bin, size);
reverse(real_part_bin.begin(), real_part_bin.end());
while(real_part_bin.back() == 0 && (int)real_part_bin.size() != 1)
{
offset--;
real_part_bin.pop_back();
}
if(real_part_bin.back() == 0)
return;
real_part_bin.pop_back();
offset--;
if(real_part_bin.size() > count_mantissa)
{
copy(real_part_bin.begin() + ((int)real_part_bin.size() - count_mantissa) , real_part_bin.end(), bin);
}else
{
copy(real_part_bin.begin(), real_part_bin.end(), bin + (count_mantissa - (int)real_part_bin.size()));
}
int por = add_por + offset;
integer_part2bin(por, poryadok);
copy(poryadok.begin(), poryadok.end(), bin+count_mantissa); //записываем в результат.
}
}
void double2bin(double number, byte *bin, const int arr_size)
{
const int count_poryadok = 11;
const int count_mantissa = 52;
const int add_por = 1023;
memset(bin, 0, sizeof(byte)*arr_size);
if(number == 0.0)
{
return;
}
if(number < 0)
bin[arr_size - 1] = 1;
number = fabs(number);
int offset = 0;
vector<byte> real_part_bin;
vector<byte> poryadok;
if(number >= 1.0)
{
int int_part = (int)number;
vector<byte> int_part_bin;
integer_part2bin(int_part, int_part_bin);
offset += int_part_bin.size() - 1;
int por = add_por + offset;
integer_part2bin(por, poryadok);
copy(poryadok.begin(), poryadok.end(), bin + count_mantissa);
copy(int_part_bin.begin(), int_part_bin.end() - 1, bin + (count_mantissa - offset));
number -= (int) number;
real_part2bin(number, real_part_bin, count_mantissa - offset);//и его двоичное представление
reverse(real_part_bin.begin(), real_part_bin.end()); //полученное представление записываем в обратном порядке
copy(real_part_bin.begin(), real_part_bin.end(), bin + (count_mantissa - offset - (int)real_part_bin.size()));
}
else //если целой части нет
{
const int size = add_por;
real_part2bin(number, real_part_bin, size);
reverse(real_part_bin.begin(), real_part_bin.end());
while(real_part_bin.back() == 0 && (int)real_part_bin.size() != 1)
{
offset--;
real_part_bin.pop_back();
}
if(real_part_bin.back() == 0)
return;
real_part_bin.pop_back();
offset--;
if(real_part_bin.size() > count_mantissa)
{
copy(real_part_bin.begin() + ((int)real_part_bin.size() - count_mantissa) , real_part_bin.end(), bin);
}else
{
copy(real_part_bin.begin(), real_part_bin.end(), bin + (count_mantissa - (int)real_part_bin.size()));
}
int por = add_por + offset;
integer_part2bin(por, poryadok);
copy(poryadok.begin(), poryadok.end(), bin+count_mantissa); //записываем в результат.
}
}
void longdouble2bin(long double number, byte *bin, const int arr_size)
{
const int count_poryadok = 15;
const int count_mantissa = 64;
const int add_por = 16383;
memset(bin, 0, sizeof(byte)*arr_size);
if(number == 0.0)
{
return;
}
if(number < 0)
bin[arr_size - 1] = 1;
number = fabs(number);
int offset = 0;
vector<byte> real_part_bin;
vector<byte> poryadok;
if(number >= 1.0)
{
int int_part = (int)number;
vector<byte> int_part_bin;
integer_part2bin(int_part, int_part_bin);
offset += int_part_bin.size() - 1;
int por = add_por + offset;
integer_part2bin(por, poryadok);
copy(poryadok.begin(), poryadok.end(), bin + count_mantissa);
copy(int_part_bin.begin(), int_part_bin.end() - 1, bin + (count_mantissa - offset));
number -= (int) number;
real_part2bin(number, real_part_bin, count_mantissa - offset);
reverse(real_part_bin.begin(), real_part_bin.end());
copy(real_part_bin.begin(), real_part_bin.end(), bin + (count_mantissa - offset - (int)real_part_bin.size()));
}
else
{
const int size = add_por;
real_part2bin(number, real_part_bin, size);
reverse(real_part_bin.begin(), real_part_bin.end());
while(real_part_bin.back() == 0 && (int)real_part_bin.size() != 1)
{
offset--;
real_part_bin.pop_back();
}
if(real_part_bin.back() == 0)
return;
real_part_bin.pop_back();
offset--;
if(real_part_bin.size() > count_mantissa)
{
copy(real_part_bin.begin() + ((int)real_part_bin.size() - count_mantissa) , real_part_bin.end(), bin);
}else
{
copy(real_part_bin.begin(), real_part_bin.end(), bin + (count_mantissa - (int)real_part_bin.size()));
}
int por = add_por + offset;
integer_part2bin(por, poryadok);
copy(poryadok.begin(), poryadok.end(), bin+count_mantissa); //записываем в результат.
}
}
bool check_float(float number, byte* bin, const int arr_size)
{
__int32 numb = *(int *)&number;
__int32 checker = 0x1;
bool return_value = true;
cout << "Проверка полученного двоичного представления с машинным представлением float"<<endl;
cout << "Полученное число: "<<endl;
for(int i = 0; i < arr_size; i++)
{
cout << (int)bin[i];
}
cout << endl << "Машинное представление: "<<endl;
for(int i = 0; i < 32; i++)
{
if(numb & checker)
cout << 1;
else
cout << 0;
checker = checker << 1;
}
checker = 0x1;
for(int i = 0; i < arr_size; i++)
{
if(bin[i] == 0 && (numb & checker))
return_value = false;
if(bin[i] == 1 && !(numb & checker))
return_value = false;
checker = checker << 1;
}
return return_value;
}
bool check_double(double number, byte* bin, const int arr_size)
{
__int64 numb = *(__int64 *)&number;
__int64 checker = 0x1;
bool return_value = true;
cout << "Проверка полученного двоичного представления с машинным представлением double"<<endl;
cout << "Полученное число: "<<endl;
for(int i = 0; i < arr_size; i++)
{
cout << (int)bin[i];
}
cout << endl << "Машинное представление: "<<endl;
for(int i = 0; i < arr_size; i++)
{
if(numb & checker)
cout << 1;
else
cout << 0;
checker = checker << 1;
}
checker = 0x1;
for(int i = 0; i < arr_size; i++)
{
if(bin[i] == 0 && (numb & checker))
return_value = false;
if(bin[i] == 1 && !(numb & checker))
return_value = false;
checker = checker << 1;
}
return return_value;
}
//
void bit4_bin2hex(vector<byte>& tetrada)
{
if(tetrada[3] == 0 && tetrada[2] == 0 && tetrada[1] == 0 && tetrada[0] == 0)//перебираем все возможные значения
cout << 0;
if(tetrada[3] == 0 && tetrada[2] == 0 && tetrada[1] == 0 && tetrada[0] == 1)
cout << 1;
if(tetrada[3] == 0 && tetrada[2] == 0 && tetrada[1] == 1 && tetrada[0] == 0)
cout << 2;
if(tetrada[3] == 0 && tetrada[2] == 0 && tetrada[1] == 1 && tetrada[0] == 1)
cout << 3;
if(tetrada[3] == 0 && tetrada[2] == 1 && tetrada[1] == 0 && tetrada[0] == 0)
cout << 4;
if(tetrada[3] == 0 && tetrada[2] == 1 && tetrada[1] == 0 && tetrada[0] == 1)
cout << 5;
if(tetrada[3] == 0 && tetrada[2] == 1 && tetrada[1] == 1 && tetrada[0] == 0)
cout << 6;
if(tetrada[3] == 0 && tetrada[2] == 1 && tetrada[1] == 1 && tetrada[0] == 1)
cout << 7;
if(tetrada[3] == 1 && tetrada[2] == 0 && tetrada[1] == 0 && tetrada[0] == 0)
cout << 8;
if(tetrada[3] == 1 && tetrada[2] == 0 && tetrada[1] == 0 && tetrada[0] == 1)
cout << 9;
if(tetrada[3] == 1 && tetrada[2] == 0 && tetrada[1] == 1 && tetrada[0] == 0)
cout << 'A';
if(tetrada[3] == 1 && tetrada[2] == 0 && tetrada[1] == 1 && tetrada[0] == 1)
cout << 'B';
if(tetrada[3] == 1 && tetrada[2] == 1 && tetrada[1] == 0 && tetrada[0] == 0)
cout << 'C';
if(tetrada[3] == 1 && tetrada[2] == 1 && tetrada[1] == 0 && tetrada[0] == 1)
cout << 'D';
if(tetrada[3] == 1 && tetrada[2] == 1 && tetrada[1] == 1 && tetrada[0] == 0)
cout << 'E';
if(tetrada[3] == 1 && tetrada[2] == 1 && tetrada[1] == 1 && tetrada[0] == 1)
cout << 'F';
}
void print_binary(byte* bin, const int arr_size)
{
if(arr_size == 32)
{
cout << "Знак: "<< (int)bin[31] <<endl;
vector<byte> por(bin + 23, bin + 31);
cout << "Порядок: " ;
for(int i = (int)por.size() - 1; i >= 0; i--)
cout << (int)por[i];
cout << " ( ";
vector<byte> tetrada;
for(int i = 8; i > 0; i -= 4)
{
tetrada.clear();
tetrada.insert(tetrada.begin(), por.begin() + (i - 4), por.begin() + i);
bit4_bin2hex(tetrada);
}
tetrada.clear();
cout << "h, "<< bin2integer_part(por) << "d )"<<endl; //выводим в десятичном виде
por.clear();
cout << "Мантисса: ";
vector<byte> mantissa(bin, bin + 23);
for(int i = (int)mantissa.size() - 1; i >= 0; i--)
cout << (int)mantissa[i];
cout << " ( 0.";
mantissa.insert(mantissa.begin(), 0);
for(int i = 24; i > 0; i -= 4)
{
tetrada.clear();
tetrada.insert(tetrada.begin(), mantissa.begin() + (i - 4), mantissa.begin() + i);
bit4_bin2hex(tetrada);
}
cout << "h, "<< bin2real_part<float>(mantissa) << "d )"<<endl; //выводим в десятичном виде
}
if(arr_size == 64)
{
cout << "\nЗнак: "<< (int)bin[63] <<endl;
vector<byte> por(bin + 52, bin + 63);
cout << "Порядок: " ;
for(int i = (int)por.size() - 1; i >= 0; i--)
cout << (int)por[i];
cout << " ( ";
por.push_back(0);
vector<byte> tetrada;
for(int i = 12; i > 0; i -= 4)
{
tetrada.clear();
tetrada.insert(tetrada.begin(), por.begin() + (i - 4), por.begin() + i);
bit4_bin2hex(tetrada);
}
tetrada.clear();
por.pop_back();
cout << "h, " << bin2integer_part(por) << "d )"<<endl;
por.clear();
cout << "Мантисса: ";
vector<byte> mantissa(bin, bin + 52);
for(int i = (int)mantissa.size() - 1; i >= 0; i--)
cout << (int)mantissa[i];
cout << " \n(0.";
for(int i = 52; i > 0; i -= 4)
{
tetrada.clear();
tetrada.insert(tetrada.begin(), mantissa.begin() + (i - 4), mantissa.begin() + i);
bit4_bin2hex(tetrada);
}
cout << "h, " << bin2real_part<double>(mantissa) << "d)"<<endl;
}
if(arr_size == 80)
{
cout << "\nЗнак: "<< (int)bin[79] <<endl;
vector<byte> por(bin + 64, bin + 79);
cout << "Порядок: " ;
for(int i = (int)por.size() - 1; i >= 0; i--)
cout << (int)por[i];
cout << " ( ";
por.push_back(0);
vector<byte> tetrada;
for(int i = 16; i > 0; i -= 4)
{
tetrada.clear();
tetrada.insert(tetrada.begin(), por.begin() + (i - 4), por.begin() + i);
bit4_bin2hex(tetrada);
}
tetrada.clear();
por.pop_back();
cout << "h, " << bin2integer_part(por) << "d)"<<endl;
por.clear();
cout << "Мантисса: ";
vector<byte> mantissa(bin, bin + 64);
for(int i = (int)mantissa.size() - 1; i >= 0; i--)
cout << (int)mantissa[i];
cout << " \n(0.";
for(int i = 64; i > 0; i -= 4)
{
tetrada.clear();
tetrada.insert(tetrada.begin(), mantissa.begin() + (i - 4), mantissa.begin() + i);
bit4_bin2hex(tetrada);
}
cout << "h, " << bin2real_part<long double>(mantissa) << "d)"<<endl;
}
}
float bin2float(byte* bin, const int arr_size)
{
const int count_poryadok = 8;
const int count_mantissa = 23;
const int add_por = 127;
float number = 0;
vector<byte> mantissa(bin, bin + count_mantissa);
vector<byte> poryadok(bin + count_mantissa, bin + count_mantissa + count_poryadok);
number = bin2real_part<float>(mantissa) + 1;
if(bin[count_poryadok + count_mantissa])
number *= -1.0;
number *= pow(2.0, bin2integer_part(poryadok) - add_por);
return number;
}
double bin2double(byte* bin, const int arr_size)
{
const int count_poryadok = 11;
const int count_mantissa = 52;
const int add_por = 1023;
double number = 0;
vector<byte> mantissa(bin, bin + count_mantissa);
vector<byte> poryadok(bin + count_mantissa, bin + count_mantissa + count_poryadok);
number = bin2real_part<double>(mantissa) + 1;
if(bin[count_poryadok + count_mantissa])
number *= -1.0;
number *= pow(2.0, bin2integer_part(poryadok) - add_por);
return number;
}
long double bin2longdouble(byte* bin, const int arr_size)
{
const int count_poryadok = 15;
const int count_mantissa = 64;
const int add_por = 16383;
long double number = 0;
vector<byte> mantissa(bin, bin + count_mantissa);
vector<byte> poryadok(bin + count_mantissa, bin + count_mantissa + count_poryadok);
number = bin2real_part<long double>(mantissa) + 1;
if(bin[count_poryadok + count_mantissa])
number *= -1.0;
number *= pow(2.0, bin2integer_part(poryadok) - add_por);
return number;
}
int bin2integer_part(vector<byte>& binary)
{
int number = 0;
for(int i = 0; i < (int)binary.size(); i++)
{
number += (int)pow((double)2, i)*(int)binary[i];
}
return number;
}
void integer_part2bin(int number, vector<byte>& binout)
{
if(number == 0)
return;
while(number != 1)
{
binout.push_back((byte)(number % 2));
number /= 2;
}
binout.push_back(1);
}
void input_vector_bin(vector<byte>& bin, const int need_size)
{
string inp;
cin >> inp;
for(int i = (int)inp.length() - 1; i >= 0; i--)
{
if(inp[i] == '0')
bin.push_back(0);
if(inp[i] == '1')
bin.push_back(1);
}
if((int)bin.size() != need_size)
bin.clear();
}
bool input_binary_interface(byte* bin, const int arr_size)
{
if(arr_size == 32)
{
vector<byte> buffer;
cout << "Введите знак(1 цифра)"<<endl;
input_vector_bin(buffer, 1);
if(buffer.empty())
{
cout << "Знак должен быть 0 или 1 (1 знак)" << endl;
return false;
}
bin[31] = buffer[0];
buffer.clear();
cout << "Введите порядок(8 цифр)" <<endl;
input_vector_bin(buffer, 8);
if(buffer.empty())
{
cout << "Порядок должен состоять из 8 знаков" << endl;
return false;
}
copy(buffer.begin(), buffer.end(), bin + 23);
buffer.clear();
cout << "Введите мантиссу(23 цифры)" <<endl;
input_vector_bin(buffer, 23);
if(buffer.empty())
{
cout << "Мантисса должна состоять из 23 знаков" << endl;
return false;
}
copy(buffer.begin(), buffer.end(), bin);
buffer.clear();
}
if(arr_size == 64)
{
vector<byte> buffer;
cout << "Введите знак(1 цифра)"<<endl;
input_vector_bin(buffer, 1);
if(buffer.empty())
{
cout << "Знак должен быть 0 или 1 (1 знак)" << endl;
return false;
}
bin[63] = buffer[0];
buffer.clear();
cout << "Введите порядок(11 цифр)" <<endl;
input_vector_bin(buffer, 11);
if(buffer.empty())
{
cout << "Порядок должен состоять из 8 знаков" << endl;
return false;
}
copy(buffer.begin(), buffer.end(), bin + 52);
buffer.clear();
cout << "Введите мантиссу(52 цифры)" <<endl;
input_vector_bin(buffer, 52);
if(buffer.empty())
{
cout << "Мантисса должна состоять из 52 знаков" << endl;
return false;
}
copy(buffer.begin(), buffer.end(), bin);
buffer.clear();
}
if(arr_size == 80)
{
vector<byte> buffer;
cout << "Введите знак(1 цифра)"<<endl;
input_vector_bin(buffer, 1);
if(buffer.empty())
{
cout << "Знак должен быть 0 или 1 (1 знак)" << endl;
return false;
}
bin[79] = buffer[0];
buffer.clear();
cout << "Введите порядок(16 цифр)" <<endl;
input_vector_bin(buffer, 16);
if(buffer.empty())
{
cout << "Порядок должен состоять из 8 знаков" << endl;
return false;
}
copy(buffer.begin(), buffer.end(), bin + 64);
buffer.clear();
cout << "Введите мантиссу(64 цифры)" <<endl;
input_vector_bin(buffer, 64);
if(buffer.empty())
{
cout << "Мантисса должна состоять из 64 знаков" << endl;
return false;
}
copy(buffer.begin(), buffer.end(), bin);
buffer.clear();
}
return true;
}
void work_with_binary()
{
int select;
cout << "Работа с введенными бинарными числами"<<endl;
cout << "Введите разрядность вводимого числа(1 - 32 бит, 2 - 64 бит, 3 - 80 бит):"<<endl;
do{
cin>> select;
}while(select != 1 && select != 2 && select != 3);
byte *bin;
bool input_success ;
switch(select)
{
case 1:
bin = new byte[32];
input_success = input_binary_interface(bin, 32);
if(!input_success)
return;
print_binary(bin, 32);
cout << "Число в десятичном исчислении: "<< bin2float(bin, 32) <<endl;
break;
case 2:
bin = new byte[64];
input_success = input_binary_interface(bin, 64);
if(!input_success)
return;
print_binary(bin, 64);
cout << "Число в десятичном исчислении: "<< bin2double(bin, 64) <<endl;
break;
default:
bin = new byte[80];
input_success = input_binary_interface(bin, 80);
if(!input_success)
return;
print_binary(bin, 80);
cout << "Число в десятичном исчислении: "<< bin2longdouble(bin, 80) <<endl;
break;
}
delete[] bin;
}
void work_with_float_numbers()
{
int select;
cout << "Работа с вещественными числами"<<endl;
cout << "Введите тип вводимого числа:\n1 - одинарной точности(float)\n2 - двойной точности(double)\n3 - расширенной точности(long double)):"<<endl;
do{
cin>> select;
}while(select != 1 && select != 2 && select != 3);
byte *bin;
float fl_number;
double db_number;
long double ld_number;
cout << "Введите вещественное число:"<<endl;
switch(select)
{
case 1:
bin = new byte[32];
cin >> fl_number;
float2bin(fl_number, bin);
print_binary(bin, 32);
if(check_float(fl_number, bin, 32))
cout << "\nВерно!"<<endl;
else
cout << "\nНеверно!!"<<endl;
break;
case 2:
bin = new byte[64];
cin >> db_number;
double2bin(db_number, bin);
print_binary(bin, 64);
if(check_double(db_number, bin, 64))
cout << "\nВерно!"<<endl;
else
cout << "\nНеверно!!"<<endl;
break;
break;
default:
bin = new byte[80];
cin >> ld_number;
longdouble2bin(ld_number, bin);
print_binary(bin, 80);
break;
}
delete[] bin;
}