Преговор - УПП, Седмица 3, 20.10.2023
Цикли, assert
Бележки от миналия път
#- Видях две груби грешки в предадените решения, първо:
 Грешно е, понежеbool b; if (condition) b = true;conditionсам по себе си е от тип bool, с тозиifбуквално не правите нищо. Правилния вариант е:
 Аналогично за:bool b = condition;
 правилното е:bool b; if (!condition) b = true;bool b = !condition;
- второ:a >= 48 && a <= 57Всяка буква действително съответства на определено число, дефинирано от ASCII стандарта. Наистина '0' е 48 и '9' е 57, обаче от вас не се очаква да помните ASCII таблицата! Също, ако не знаеш наизуст кои буква са тези числа, този израз е много неясен. Правилния вариант е просто да направите сравнения с буквите, все пак C++ ги "конвертира" (много грубо казано) към съответните ASCII стойности: a >= '0' && a <= '9'
С/без загуба на данни
#Получи се малко разногласие между това, което Ивана ви е казала и това което аз ви казах. В края на деня, конвертиране от int към unsigned int не губи информация!
Цитирайки 4то издание на "The C++ Programming Language" глава 10.5:
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Тоест, конвертирания при които не губиш битове, нямаш загуба на данни.
2s compliment
#Интуитивно обяснение на 2s compliment. Да приемем, че работим с тип данни, при който имаме само 3 бита.
Как бихме ги използвали, за да представим отрицателните числа?
Най-лесния начин е да погледнем най-левия (старшия) бит, ако е 0 значи е положително, ако е 1 значи е отрицателно, тоест 010 е 2, докато 110 е -2.
Ако разпишем всичките ни числа:
111 -3
110 -2
101 -1
100 -0
011  3
010  2
001  1
000  0
Това работи, обаче имаме един гигантски проблем: събирането не работи! От математика знаем, че "2 - 1 = 2 + (-1)", тоест би трябвало да можем да съберем побитово 2 и -1 и да получим 1. Ама,
2 + -1 = 010 + 101 = 111 = -3
Също, знаем, че "(-1) + (-1) = -2", обаче
-1 + -1 = 101 + 101 = 1010 имаме overflow, това се съкращава на 010 = 2
Излиза, че с тази схема не можем да събираме отрицателни числа както събираме положителни (или както събираме побитово).
Да не говорим, че ние имаме -0, което не ни трябва много.
011 3
010 2
001 1
001 + 111 = 1000 overflow, става 000
Правейки същото за "2 + -2", намираме че
010 + 110 = 1000 overflow, става 000
111 -1
110 -2
101 -3
100  x
011  3
010  2
001  1
000  0
Това е идеята на "complements", дефинираме отрицателни числа, така че да използваме едно и също събиране между положителни и отрицателни.
Още от много старите "калкулатори" (сумиращи машини), изваждането се е свеждало до събиране на положително и отрицателно число.
И това е причината защо ~ 2 връща -3:
~ 00000000000000000000000000000010
──────────────────────────────────
  11111111111111111111111111111101
>> със знаков тип имаме аритметическо отместване:
11111111111111111111111111111101 >> 1
─────────────────────────────────────
11111111111111111111111111111110
Цикли
#- whileцикъл
 "условие" е булева стойност, като ако е- while (условие) { тяло }- falseцикъла спира, докато ако е- true"тяло" се изпълнява и после пак се проверява условие
  if (условие) {
      тяло
  }
  else {
      спри
  }
  if (условие) {
      тяло
  }
  else {
      спри
  }
  ...
- do-whileцикъл, като- while, но "тяло" се изпълнява поне един път
 Нашият аналог е:- do { тяло } while (условие);- тяло if (условие) { тяло } else { спри } if (условие) { ...
- forцикъл
 "инициализация" се изпълнява само веднъж, преди всичко останало в цикъла- for (инициализация; условие; инкрементация) { тяло }
 "условие" се изпълнява преди всяка итерация, като ако е- falseцикъла спира, докато ако е- trueпродължава
 "инкрементация" се изпълнява след края на всяка итерация
- Може да си представяте, че това на практика извършва:инициализация if (условие) { тяло } else { спри } инкрементация if (условие) { тяло } else { спри } ...
- или използвайкиwhileцикъл:инициализация while (условие) { тяло инкрементация }
Ключови думи
#- break: моментално прекратява изпълнението на цикъла- При - forцикли инкрементацията не се изпълнява след- break
- continue: продължи след края на сегашната итерация; тоест изпълнението на тяло се прекратява и започваме нова итерация- При - forцикли директно отива на инкрементация
Assert
#Понякога е полезно да тестваме нашия код вътре в самия код. Тоест, искаме на конкретно място в кода да проверим нещо.
assert(condition);
Ако condition е true, нищо не се случва, обаче ако е false програмата моментално прекратява изпълнение.
Използва се повече като програмистки уред, тоест ако програмата спре заради assert, това е защото има някаква програмистка грешка.