Програмирање 2/К1П 2019
Питања
1. питање
На неком рачунару, реални бројеви се представљају на ширини од 10 бита у формату сееееммммм, где је с предзнак броја, ееее су битови експонента у коду са вишком 7 и ммммм су бити нормализоване мантисе са скривеним битом (1≤М<2). Цели бројеви се представљају на ширини од 8 бита у комплементу двојке. Нека се у целобројној локацији А налази број чија је представа 8216, док се у реалној локацији Б налази број чија је вредност 13.2510. Како на датом рачунару изгледа представа броја који је резултат операције А + Б? Сва заокруживања се обављају према правилима АНСИ/ИЕЕЕ стандарда за реалне бројеве.
Поставка
Треба сабрати два реална броја. За почетак претворимо оно што нам је дато у реалне бројеве по формату.
- Број бити експонента је к = 4
- Вишак (ИЕЕЕ) је в = 24-1-1 = 7
- Број бити мантисе је п = 5
- Мантиса је ИЕЕЕ формата 1.xxxxx
Број А
8 бита, комплемент 2, дакле последњи бит одређује знак. А = 8216 = 1000 0010. Број је очигледно негативан. Комплементирамо да извучемо вредност. А = - 111 1110 = -126.
Треба нормализовати овај број да би стао у формат мантисе. 111 1110 => 1.11 1110. Померањем улево за 6 места добијамо број Аф = - 1.111110 * 26. Експонент Е = 6. Подвлачимо мантису: MА = 11111. Овде није било заокруживања (правило 1). Тако да је број у запису -1.11111 * 26.
Број Б
Б = 13.25. Претварамо одвојено цели и децимални део. 1310 = 11012 0.2510 = 0.012 Спојимо и добијемо 1101.01. Нормализујемо тако да стане у формат мантисе померањем зареза улево. 1.10101 * 23. Експонент је Е = 3. Број Бф = 1.10101 * 23.
Сабирање
Број Б се доводи на већи експонент, при томе се заокружује мантиса (правило 2). Бф = 1.10101 * 23 = 0.00110101 * 26 = 0.00111 * 26.
Очекујемо негативан број јер је |А|>|Б|. Одузимамо реалне бинарне бројеве: Аф + Бф = 0.00111 * 2 6 - 1.11111 * 26 = -(1.11111 * 26 - 0.00111 * 2 6) = - 1.11000 * 26.
Репрезентација
Наш број је - 1.11000 * 26. Конвертујемо га у представу формата:
с ееее ммммм
Знак је - па је бит с 1.
1 ееее ммммм
Експоненту додајемо померај (вишак). е = Е + в = 6 + 7 = 13 = 11012.
1 1101 ммммм
Мантису препишемо
1 1101 11000
Претворимо у хеx број:
0011 1011 1000 = 3Б8.
2. питање
На неком рачунару, реални бројеви се представљају на ширини од 10 бита у формату сееееммммм, где је с бит предвиђен за кодирање предзнака броја, ееее су 4 битова за експонент у коду са вишком 7, а ммммм су бити нормализоване матисе са скривеним битом (1≤М<2). На овом рачунару се учитавају два цела броја који се смешају у реалне локације и чије су вредности 240 и 13. Потом се исти бројеви саберу и резултат упише у трећу реалну локацију. Која је апсолутна вредност разлике добијеног резултата и потпуно тачног збира унетих бројева? Сва заокруживања се обављају према правилима АНСИ/ИЕЕЕ стандарда за реалне бројеве.
Поставка
- w = 10
- к = 4, в = 7 (ИЕЕЕ)
- п = 5
- ИЕЕЕ формат мантисе 1.xxxxxx
Треба сабрати реалне бројеве А и Б, тражи се грешка тј апсолутна вредност разлике добијеног резултата и потпуно тачног збира. Потпуно тачан збир З = А + Б = 240 + 13 = 253.
Број А
А = 24010.
Претворимо у бинарни број: А = 1111 0000 * 20. Треба нормализовати мантису, па заокружити на број битова.
А = 1111 0000 * 20 = 1.1110000 * 27. (Правило 1)
Аф = 1.11100 * 27.
Број Б
Б = 1310
Применити исти поступак. Б = 1310 = 11012 * 20.
Нормализација: Б = 1.101 * 23
Неопходно је довести на исти експонент ради сабирања померањем улево за 4:
Б = 0.0001101 * 27.
Б = 0.00011 01 * 27.
Бф = 0.00011 * 27.
Сабирање
С = Аф + Бф = 1.11100 * 27 + 0.00011 * 27 = 1.11111 * 27.
С = 1.11111 * 27 = 1111 1100 = 240 + 12 = 252.
Р = |С-З| = |252-253| = 1. (Б)
3. питање
#include <stdio.h>
int main(void) {
int nums[] = { 0x21, -3, 011, 5, 04, 0 }, s = 0;
// Niz će imati vrednosti 33, -3, 9, 5, 4, 0.
// Uslov se računa kao veličina niza kroz veličina jednog člana, što daje broj članova, ali jedan manje jer se u foru gleda sledeći član.
for(int i=0; i<sizeof(nums)/sizeof(int)-1; i++) {
// Prvi i sledeći član.
int x = nums[i], y = nums[i+1];
int mask = x >> sizeof(int)*8 - 1;
// * i - ima prednost u odnosu na >>. Uzmimo da je int veličine 4.
// mask = x >> 4*8 - 1
// mask = x >> 31
// Očigledno je da se ovde pomera 31 bit da bi na najnižem dobili bit za znak.
// Stvar je u tome što za negativne brojeve, pomeranje udesno za negativne brojeve sa desne strane uvodi 1 a ne 0 da bi se zadržao znak.
// Npr 0x21 >> 31 = 0b00000000
// Ali -3 = 1111 .... 1101 >> 31 = 1111 .... 1111 tj maska sa sve 1.
x = (x + mask) ^ mask;
// Ovde pozitivni brojevi ostaju nepromenjeni, a negativnima se dodaje maska pa okreće svaki bit. U prevodu - okreće im se znak komplementiranjem i postaju pozitivni.
while(y > 0) {
// Ako je član desno od trenutnog paran, dodaj na sumu x.
if(y&1) s += x;
// Množimo trenutni sa 2
x <<= 1;
// Delimo naredni sa 2. Uslov whilea je da se ponavlja dok y ne postane 0.
y >>= 1;
}
// Ovo je egipćanski algoritam za množenje dva broja star hiljadama godina, množi dva susedna broja i dodaje ih na sumu. Još jedan dokaz da je Milo zapravo faraon.
}
printf("%d", s);
}
4. питање
Ова питалица се реши на поглед. Једино треба проверити да ли је (Б) или ниједан од понуђених одговора. Функција принтф никад неће вратити стринг ако јој је дат форматски спецификатор %д. Називи енумова постоје само у коду и губе се током компилације, тако да је једино смислено решење (Б) 3 91.