Міністерство освіти і науки України
Національний університет „Львівська політехніка”
Лабораторна робота №3
з дисципліни: “Програмування, частина 3 (Структури даних та алгоритми)”
Мета роботи
Дослідження методів та засобів явного та неявного перетворення типів даних
Завдання на лабораторну роботу
Завдання 1:
Визначити, які неявні перетворення типів будуть відбуватись при обчисленнях. З’ясувати, чи відбудуться втрати значимості даних. Хід міркувань підтвердити програмними результатами. В звіти пояснити кожне перетворення і метод, яким воно здійснено.
typedef unsigned int type_0;
typedef unsigned short int type_1;
typedef unsigned long int type_2;
typedef signed short int type_3;
typedef signed int type_4;
typedef signed long int type_5;
typedef bool type_6;
typedef char type_7;
typedef wchar_t type_8;
typedef float type_9;
typedef double type_10;
typedef long double type_11;
// позначимо через DN - день народження, MN – місяць народження
char x0=0; // замість № підставити значення: DN % 9
unsigned int x1=25; // замість № підставити значення: DN % DN
signed long int x2=2; // замість № підставити значення: MN % 9
signed long int x3=3; // замість № підставити значення: MN % 13
wchar_t x4=4; // замість № підставити значення: (DN * MN) % 9
unsigned short int x5=5; // замість № підставити значення: DN % 12
unsigned long int x6=6; // замість № підставити значення: MN % 3
signed long int x7=7; // замість № підставити значення: (DN * MN) % 12
long double x8=8; // замість № підставити значення: DN % 13
signed long int x9=9; // замість № підставити значення: MN % 6
signed long int x10=10; // замість № підставити значення: (DN * MN) % 10
unsigned short int x11=11; // замість № підставити значення: DN % 3
/* 1 */ x1 = x1 – 0xFFFFFFFA;
/* 2 */ x3 = ’a’ + x0 – x2;
/* 3 */ x7 = x4 + x5 + x6 * 0.1;
/* 4 */ x8 = x9 + x10 – x11*10;
Завдання 2
Визначити, які явні і неявні перетворення типів будуть відбуватись. Результати обчислень підтвердити програмними результатами. В звіти пояснити кожне перетворення і кожний отриманий результат.
// позначимо через DN і MN числа, що відповідають дню і місяцю народження,
// через dn і mn – по дві цифри, що відповідають дню і місяцю народження,
// наприклад: DN=5 , MN=3 , dn=05 , mn =03
const int x_0= 12500; // наприклад: 5*3*100=1500 => x_0=1500;
const double y_1= 1.25; // наприклад: 5*3/100=0.15 => y_0=0.15;
int x = х_0; // замість № підставити значення: DN % 5
double y = y_1; // замість № підставити значення: DN % 3
char v0=*reinterpret_cast<char*> (&x) +3; printf("%d %x %c \n", v0,v0,v0);
char v5=*reinterpret_cast<char*> (&x) +2; printf("%d %x %c \n", v5,v5,v5);
long w1 =*reinterpret_cast<long*>(&y)+33; printf("%lx %lu %ld \n", w1,w1,w1);
short w6=*(reinterpret_cast<short*>(&y)+3)+13; printf("%x %u %d \n", w6,w6,w6);
Вибір індивідуального завдання
Вибрати назви змінних для дослідження в завданні 2 згідно з варіантом з таблиці:
(місяць народження студента) % 4
(день народження студента) % 4
0
1
2
3
0
v0 , w1 ,
v3 , w4
v1 , w2 ,
v4 , w5
v2 , w3 ,
v5 , w6
v3 , w4 ,
v6 , w7
1
v4 , w5 ,
v7 , w8
v5 , w6 ,
v0, w1
v6 , w7 ,
v1 , w2
v7 , w0 ,
v2 , w3
2
v0 , w2,
v4, w7
v1 , w3 ,
v5 , w0
v2 , w4 ,
v6 , w1
v3 , w5 ,
v7 , w2
3
v4 , w6 ,
v0 , w3
v5 , w7 ,
v1, w4
v6 , w0,
v2 , w5
v7 , w1 ,
v3 , w6
Моя дата народження: 25.05.2000, варіант – v5 , w6, v0 , w1
Пояснення результатів
Завдання 1
x1 = x1 – 0xFFFFFFFA;
unsigned int x1=25
ВПК: 19 00 00 00
0xFFFFFFFA16 = 610
ВПК: FAFFFFFF −> FAFFFFFF
Комп’ютер знає тільки дію додавання, вираз набуде вигляду:
x1 = x1+ (–0xFFFFFFFA)
Тоді:x1 = 25 +(- 6) = 1910, а тип даних залишається unsigned int
x3 = ’a’ + x0 – x2;
ВПК: 5F 00 00 00 (9510 = 5F16)
signed long int x2=2
ВПК: 02 00 00 00
char 'a' - значення 9710=6116 за таблицею ASCII
ВПК: 61 00
char x0=0
ВПК: 00 00
signed long int x3=3
ВПК: 03 00 00 00
char −> unsigned long int
Mетод: розширення знаком
Далі типи не міняються, бо вони співпадають.
Тоді: x3 = ’a’ + x0 – x2 = 97 + 0 +(-2) = 9510
x7 = x4 + x5 + x6 * 0.1;
ВПК: 33 33 33 33 33 33 23 40
double x7 = 7;
signed int x4 = 4;
long double x5 = 5;
unsigned long int x6 = 6;
double 0.1;
double 0.1
ВПК: 9A 99 99 99 99 99 B9 3F
Signed int x4 + long double x5;
signed int −> long double
Mетод: представляється як double, можлива втрата точності
ВПК: 04 00 00 00 −> 00 00 00 00 00 00 22 40
unsigned long int x6 * double 0.1;
unsigned long int −> double
Mетод: перетворення long в double
ВПК: 06 00 00 00 −> 33 33 33 33 33 33 E3 3F
(long double x4 + x5) + (double x6 *0.1)
double −> long double
Метод: розширення
Присвоєння
long double −> double
Mетод: представляється як double, якщо long не може бути представлене точно, то відбувається деяка втрата точності
ВПК: 00 00 00 00 00 00 18 40
Тоді: x7=4+5+6*0.1=9.6
x8 = x9 + x10 – x11*10;
ВПК: 00 00 А0 F4 FF FF EF 41
long double x8 = 8;
unsigned long int x9 = 9;
unsigned long int x10 = 10;
unsigned long int x11 = 11;
long double 10;
unsigned long int x11=11 * long double 10
ВПК: 00 00 00 00 00 00 26 40 −> 00 00 00 00 00 80 5B 40
unsigned long int −> long double
Метод: long в double, поява знакової частини
unsigned long int х9=9 + unsigned long int х10=10
ВПК: 00 00 00 00 00 00 26 40 −>00 00 00 00 00 33 40
Тип не міняється.
(unsigned long int х9 + x10) + (long double x11*10)
unsigned long int −> long double
Метод: long в double, поява знакової частини
x8=9+10-11*10=19-110= -9110=>-5B16ВПК 5B : 5B 00 00 00 , оскільки - 5B зробивши інверсію та додавши 1
=> A5 FF FF FF16 = 429496720510
Мантиса: 1111111111111111111111110100101000000000000000000000
Зміщений порядок: 10000011110
Результат: 429496720510
Завдання 2
const int x_0 = 125008 = 154016
const double y_1 = 1.25 = D316
int x = x_0;
double y = y_1;
char v0=*reinterpret_cast<char*> (&x) +3; printf("%d %x %c \n", v0,v0,v0);
reinterpret_cast дозволяє перетворювати вказівник одного типу в інший.
Спершу тип int змінної «х» інтерпретується як char, іде збереження молодшого байта.За допомогою (&x) +3 вибирається необхідний байт.
Далі char на виводі printf(("%d …) перетворюється знову в int.
ВПК x =40 15 00 00
char займає 1 байт, маєм що у=4016=0100 00002 , оскільки, знак “+”,
отримаєм: 64+3=67
Відповідь: 67 43 C
67 – отриманий результат в 10-ій системі числення;
43 – отриманий результат в 16-ій системі числення (4316=6710);
'C' – З таблиці ASCII під номером 3510 знаходиться символ 'C' ;
char v5=*reinterpret_cast<char*> (&x) +2; printf("%d %x %c \n", v5,v5,v5);
reinterpret_cast дозволяє перетворювати вказівник одного типу в інший.
Спершу тип int змінної «х» інтерпретується як char, іде збереження молодшого байта.За допомогою (&x) +2 вибирається необхідний байт.
Далі char на виводі printf(("%d …) перетворюється знову в int.
ВПК x =40 15 00 00
char займає 1 байт, маєм що у=4016=0100 00002 , оскільки, знак “+”,
отримаєм: 64+1=65
Відповідь: 65 41 A
65 – отриманий результат в 10-ій системі числення;
41 – отриманий результат в 16-ій системі числення (4316=6710);
'A' – З таблиці ASCII під номером 3510 знаходиться символ 'A' ;
long w1 =*reinterpret_cast<long*>(&y)+33; printf("%lx %lu %ld \n", w1,w1,w1);
Оскільки, double- дійсне чило а long- ціле, то відкидається дробова частина: 1.0 −> 1 і додається 33
1+33=34
Відповідь: 22 34 34
22 – отриманий результат в 16-ій системі числення(3410=2216) ;
34 – отриманий результат представляється як unsigned long, оскільки тип без знаковий а число додатнє , то залишиться таким же;
34 – отриманий результат в 10-ій системі числення
short w6=*(reinterpret_cast<short*>(&y)+3)+13; printf("%x %u %d \n", w6,w6,w6);
Тип double змінної «y» інтерпретується як short, виконується перетворення в тип short. За допомогою (&y) +2 вибирається необхідний байт.Далі додається 1210 та при виводі зберігається тип даних.
y = 21110; його ВПК : 00 00 00 00 00 60 6А 40
Беремо 3 і 4 байт, бо (&y)+2 => 60 00
60 0016 + 1210 = 60 0С
ВПК: 0C 60, оскільки, short займає 2 байта
60 0C16 – 2458810
Відповідь: 600C 24588 24588
60 0C – отриманий результат в 16-ій системі числення в,
24588 – отриманий результат в 10-ій системі числення
Результати виконання програми
Рис. 1 Виконання програми
Висновок: реалізував програму, дослідив методи та засоби явного і неявного перетворення типів даних
Реалізація у програмному коді
#include <iostream>
#include<stdio.h>
#include<conio.h>
#include<iomanip>
using namespace std;
int main() {
setlocale(LC_ALL, "ru");
setlocale(LC_ALL, "ukr");
typedef unsigned int type_0;
typedef unsigned short int type_1;
typedef unsigned long int type_2;
typedef signed short int type_3;
typedef signed int type_4;
typedef signed long int type_5;
typedef bool type_6;
typedef char type_7;
typedef wchar_t type_8;
typedef float type_9;
typedef double type_10;
typedef long double type_11;
type_7 x0 = 0;
type_0 x1 = 11;
type_5 x2 = 2;
type_5 x3 = 3;
type_8 x4 = 4;
type_1 x5 = 5;
type_2 x6 = 6;
type_5 x7 = 7;
type_11 x8 = 8;
type_5 x9 = 9;
type_5 x10 = 10;
type_1 x11 = 11;
/* 1 */ x1 = x1 - 0xFFFFFFFA;
/* 2 */ x3 = 'a' +x0 - 2;
/* 3 */ x7 = x4 + x5 + x6 * 0.1;
/* 4 */ x8 = x9 + x10 - x11 * 10;
cout << x1 << endl << x3 << endl << x7 << endl << setprecision(20)<< x8 << endl << "_______________" << endl;
const int x_0 = 12500;
const double y_1 = 1.25;
int x = x_0;
double y = y_1;
char v0=*reinterpret_cast<char*> (&x) +3; printf("%d %x %c \n", v0,v0,v0);
char v5=*reinterpret_cast<char*> (&x) +2; printf("%d %x %c \n",
v5,v5,v5);
long w1 =*reinterpret_cast<long*>(&y)+33; printf("%lx %lu %ld
\n", w1,w1,w1);
short w6=*(reinterpret_cast<short*>(&y)+3)+13; printf("%x %u %d \n",
w6,w6,w6);
cout << "________________"<< endl << "VPK:" << endl;
unsigned char *xx = (unsigned char *)(&x1);
for (int i = 0; i<sizeof(x1); i++)
printf("%02X ", xx[i]);
printf("\n");
unsigned char *xx1 = (unsigned char *)(&x3);
for (int i = 0; i<sizeof(x3); i++)
printf("%02X ", xx1[i]);
printf("\n");
unsigned char *xx2 = (unsigned char *)(&x7);
for (int i = 0; i<sizeof(x7); i++)
printf("%02X ", xx2[i]);
printf("\n");
unsigned char *xx3 = (unsigned char *)(&x8);
for (int i = 0; i<sizeof(x8); i++)
printf("%02X ", xx3[i]);
printf("\n");
unsigned char *vv1 = (unsigned char *)(&v0);
for (int i = 0; i<sizeof(v0); i++)
printf("%02X ", vv1[i]);
printf("\n");
unsigned char *vv2 = (unsigned char *)(&v5);
for (int i = 0; i<sizeof(v5); i++)
printf("%02X ", vv2[i]);
printf("\n");
unsigned char *vv3 = (unsigned char *)(&w1);
for (int i = 0; i<sizeof(w1); i++)
printf("%02X ", vv3[i]);
printf("\n");
unsigned char *vv4 = (unsigned char *)(&w6);
for (int i = 0; i<sizeof(w6); i++)
printf("%02X ", vv4[i]);
printf("\n");
system("pause");
}