'def title Преговор - УПП, Седмица 3, 20.10.2023 'def desc Преговор на материала # {title} \n {presentation-controller} :title_slide35 # Цикли, assert :slide25 ## Бележки от миналия път :unordered - Видях две груби грешки в предадените решения, първо: ```cpp bool b; if (condition) b = true; Грешно е, понеже {` condition} сам по себе си е от тип bool, с този {` if} буквално не правите нищо. Правилния вариант е: ```cpp bool b = condition; Аналогично за: ```cpp bool b; if (!condition) b = true; правилното е: ```cpp bool b = !condition; :middle_slide :unordered - второ: ```cpp a >= 48 && a <= 57 .p Всяка буква действително съответства на определено число, дефинирано от ASCII стандарта. Наистина '0' е 48 и '9' е 57, обаче от вас {b не} се очаква да помните ASCII таблицата! Също, ако не знаеш наизуст кои буква са тези числа, този израз е много неясен. .p Правилния вариант е просто да направите сравнения с буквите, все пак C++ ги "конвертира" (много грубо казано) към съответните ASCII стойности: ```cpp a >= '0' && a <= '9' :slide ## С/без загуба на данни {br3} .p Получи се малко разногласие между това, което Ивана ви е казала и това което аз ви казах. В края на деня, {b конвертиране от int към unsigned int не губи информация!} .p Цитирайки 4то издание на "The C++ Programming Language" глава 10.5: .quote A conversion is value-preserving if you can convert a value and then convert the result back to it's original type and get the original value Тоест, конвертирания при които не губиш битове, нямаш загуба на данни. :slide ## 2s compliment .p Интуитивно обяснение на 2s compliment. Да приемем, че работим с тип данни, при който имаме само 3 бита. .p Как бихме ги използвали, за да представим отрицателните числа? Най-лесния начин е да погледнем най-левия (старшия) бит, ако е 0 значи е положително, ако е 1 значи е отрицателно, тоест {` 010} е 2, докато {` 110} е -2. Ако разпишем всичките ни числа: ``` 111 -3 110 -2 101 -1 100 -0 011 3 010 2 001 1 000 0 :middle_slide .p Това работи, обаче имаме един гигантски проблем: събирането не работи! От математика знаем, че "2 - 1 = 2 + (-1)", тоест би трябвало да можем да съберем побитово 2 и -1 и да получим 1. Ама, ``` 2 + -1 = 010 + 101 = 111 = -3 .p Също, знаем, че "(-1) + (-1) = -2", обаче ``` -1 + -1 = 101 + 101 = 1010 имаме overflow, това се съкращава на 010 = 2 .p Излиза, че с тази схема не можем да събираме отрицателни числа както събираме положителни (или както събираме побитово). .p Да не говорим, че ние имаме -0, което не ни трябва много. :middle_slide Нека да помислим пак, да вземем само положителните: ``` 011 3 010 2 001 1 Сега, искаме -1 да бъде такова число, различно от досега дефинираните (тоест което има единица в старшия си бит) така че "1 + -1 = 0". Лесно се досещаме, че ако добавим към "001" числото "111", тогава тяхната сума ще предизвика overflow и резултата ще бъде 0: ``` 001 + 111 = 1000 overflow, става 000 Нека тогава "-1 = 111". :slide .p Правейки същото за "2 + -2", намираме че ``` 010 + 110 = 1000 overflow, става 000 Нека тогава "-2 = 110". За "3 + -3" се досещаме, че "-3 = 101". За сега имаме: ``` 111 -1 110 -2 101 -3 100 x 011 3 010 2 001 1 000 0 100 не сме го използвали, обаче намерихме отрицателното число за всяко положително. Да видим как работим с него, побитово "100 + 001 = 101", тоест "x + 1 = -3", следователно x ще бъде -4. :middle_slide .p Това е идеята на "complements", дефинираме отрицателни числа, така че да използваме едно и също събиране между положителни и отрицателни. .p Още от много старите "калкулатори" ({url сумиращи машини;https://en.wikipedia.org/wiki/Adding_machine}), изваждането се е свеждало до събиране на положително и отрицателно число. .p И това е причината защо {` ~ 2} връща {` -3}: ``` ~ 00000000000000000000000000000010 ────────────────────────────────── 11111111111111111111111111111101 И затова при {` >>} със знаков тип имаме аритметическо отместване: ``` 11111111111111111111111111111101 >> 1 ───────────────────────────────────── 11111111111111111111111111111110 :slide ## Цикли {br4} :unordered - {` while} цикъл ```cpp while (условие) { тяло } "условие" е булева стойност, като ако е {` false} цикъла спира, докато ако е {` true} "тяло" се изпълнява и после пак се проверява условие :middle_slide - Може да си го представите като ````cpp if (условие) { тяло } else { спри } if (условие) { тяло } else { спри } \... :slide :unordered - {` do-while} цикъл, като {` while}, но "тяло" се изпълнява поне един път ```cpp do { тяло } while (условие); Нашият аналог е: ````cpp тяло if (условие) { тяло } else { спри } if (условие) { \... :middle_slide :unordered - {` for} цикъл ```cpp for (инициализация; условие; инкрементация) { тяло } "инициализация" се изпълнява само веднъж, преди всичко останало в цикъла\n "условие" се изпълнява преди всяка итерация, като ако е {` false} цикъла спира, докато ако е {` true} продължава\n "инкрементация" се изпълнява след края на всяка итерация :slide :unordered - Може да си представяте, че това на практика извършва: ````cpp инициализация if (условие) { тяло } else { спри } инкрементация if (условие) { тяло } else { спри } \... :middle_slide :unordered - или използвайки {` while} цикъл: ```cpp инициализация while (условие) { тяло инкрементация } :slide ### Ключови думи {br3} :unordered - {` break}: моментално прекратява изпълнението на цикъла .p При {` for} цикли инкрементацията не се изпълнява след {` break} {br2} - {` continue}: продължи след края на сегашната итерация; тоест изпълнението на тяло се прекратява и започваме нова итерация .p При {` for} цикли директно отива на инкрементация :slide ## Assert {br3} .p Понякога е полезно да тестваме нашия код вътре в самия код. Тоест, искаме на конкретно място в кода да проверим нещо. ```cpp assert(condition); .p Ако {` condition} е {` true}, нищо не се случва, обаче ако е {` false} програмата моментално прекратява изпълнение. .p Използва се повече като програмистки уред, тоест ако програмата спре заради {` assert}, това е защото има някаква програмистка грешка.