argon bulletin board

Факултети => Факултет по математика и информатика => Темата е започната от: Jack Johnson в 17.01.2011, 18:22:04

Титла: Една задачка - закачка!
Публикувано от: Jack Johnson в 17.01.2011, 18:22:04
Ако "а = 3", тогава каква е стойността на "a" след изпълнението на следния израз:

a += a++ + ++a
Това е малко в стил "вижте колко шантав код може да измисли човек", но е добро упражнение за мозъка. Който иска да види крайния отговор без да си размърда мозъчните клетки, copy/paste на долния ред в URL полето на браузъра и Enter.

javascript:{var a = 3; a += (a++ + ++a); alert(a);}
P.S. Ами ако "а = 4"?
Титла: Re:Една задачка - закачка!
Публикувано от: xyz-- в 17.01.2011, 20:24:19
Интересен код.
4 += (4 + 6), което е равно на 14 е отговорът, показан от browser-а.
Като го компилирам с gcc, става друго.
a += (4 + 6), понеже след ++ a=6, крайното е 16.
Може би реализациите са различни.
Титла: Re:Една задачка - закачка!
Публикувано от: lamerko в 17.01.2011, 20:26:34
11; 14;

Или:

3 += (3++ + 4) = 3 += 8 = 11;
4 += (4++ + 5) = 4 += 10 = 14;

И какъв е смисъла да слагаш решението :)

ed:

xyz++: всичко опира до интерпретация на ++х и х++
Титла: Re:Една задачка - закачка!
Публикувано от: antoniy в 17.01.2011, 23:23:14
xyz++: всичко опира до интерпретация на ++х и х++

Всъщност всичко опира до приоритета на всички оператори. Аз мога да си измисля език, в който да объркам целия ни общоприет математически и софтуерен приоритет на операторите и там никой не може да каже какво ще се получи. Заради това се разглежда конкретен случай - конкретен език и компилатор/транслатор.
Титла: Re:Една задачка - закачка!
Публикувано от: Светослав Енков в 19.01.2011, 00:41:17
Да, на практика Иван не указва изрично, че визира Javascript, но се подразбира с даденият от него пример за 'бърза проверка'. Интересно ми е, дали наистина JS спазва 100% всички приоритети на С++? По принцип знам, че уж ги 'наследява' от него, както и че тези в С++ са нещо като 'неявен стандарт'.

Лично аз избягвам да пиша такива двусмислени изрази. Най-вече, защото работя на няколко езика (Паскал, С/С++/C#, РНР) и понякога интересни фрагменти код ми се налага да ги 'портирам' от един на друг език за различните проекти. Ех, къде е Вавилонската рибка за кодерите?

М/у другото - аз избягвам да давам подобни задачки-закачки на студентите ми по С++, но съм виждал как в разни други ВУЗ-чета ги дават много смело и безотговорно по контролни и тестове... Искам да могат да мислят алгоритми, е това включва и разгадаване на подобен род неща, ама де да беше това най-важното, нали?

И оше, подобен род изрази, ако компилаторът не успее да ги опрости автоматично, как ли объркват процесора и редът на изпълнение на операциите? Горкичкото CPU! (не че го мисля)
Титла: Re:Една задачка - закачка!
Публикувано от: lamerko в 19.01.2011, 01:28:58
Ами аз имах предвид, че горния пример ще сработи различно при различните компилатори. Например при PHP и C резултатите са 13 и 16, но при C# и JavaScript (Mozilla/Webkit) - 11 и 14. Сигурен съм, че би дал различен резултат на два различни компилатора на един и същи език  :) И точно поради това този пример наистина не е удачен.

Иначе разликите се получават не заради разликата в приоритетите на операциите, а просто в начина, по който се модифицират променливите.
Титла: Re:Една задачка - закачка!
Публикувано от: antoniy в 19.01.2011, 10:30:56
Иначе разликите се получават не заради разликата в приоритетите на операциите, а просто в начина, по който се модифицират променливите.

Моля, обясни за непосветените като мен, за да знаем от тук нататък.
Титла: Re:Една задачка - закачка!
Публикувано от: lamerko в 19.01.2011, 12:32:56
Ами например ако a = 4, имаме израза: а+= (a++ + ++a); Това, което аз казвам е, че при PHP и C ще върне 16. Първо се изпълнява израза в скобите - неговия резултат е 10 - имаме 3 операции, 2-те с по-висок приоритет. При операцията ++а, а става 5. а++ се изпълнява, но все още не модифицирала променливата... когато идва операцията за събиране - модифицира променливата и събира. Така израза ВРЪЩА 10, НО СЪЩЕВРЕМЕННО променливата а = 6, а не на 4. Докато JavaScrip и C# няма да модифицират променливата извън израза в скобите.
Титла: Re:Една задачка - закачка!
Публикувано от: Jack Johnson в 19.01.2011, 15:33:56
Ами например ако a = 4, имаме израза: а+= (a++ + ++a); Това, което аз казвам е, че при PHP и C ще върне 16. Първо се изпълнява израза в скобите - неговия резултат е 10 - имаме 3 операции, 2-те с по-висок приоритет. При операцията ++а, а става 5. а++ се изпълнява, но все още не модифицирала променливата... когато идва операцията за събиране - модифицира променливата и събира. Така израза ВРЪЩА 10, НО СЪЩЕВРЕМЕННО променливата а = 6, а не на 4. Докато JavaScrip и C# няма да модифицират променливата извън израза в скобите.

Now I'm officially impressed... изобщо не ми беше хрумнало да тествам кода на нещо друго, освен JavaScript!

В такъв случай даже ме е страх да питам какви ще са стойностите на a, b и c след изпълнение на следния код:

a = 3
b = 4
c = a+++b

Третият ред изглежда като грешка, но е напълно валиден!  :wink:

javascript:{var a = 3; var b = 4; var c = a+++b; alert("a = " + a + ", b = " + b + ", c = " + c);}


PS: Въпросът е дали се изпълнява това:

a++ + b
или това:

a + ++b
Титла: Re:Една задачка - закачка!
Публикувано от: Beginner в 19.01.2011, 15:42:11
Иначе разликите се получават не заради разликата в приоритетите на операциите, а просто в начина, по който се модифицират променливите.
Как би обяснил тогава:
а += а++ + ++а   <=> 16
a = a + a++ + ++a  <=> 14
Титла: Re:Една задачка - закачка!
Публикувано от: lamerko в 19.01.2011, 16:24:54
Иначе разликите се получават не заради разликата в приоритетите на операциите, а просто в начина, по който се модифицират променливите.
Как би обяснил тогава:
а += а++ + ++а   <=> 16
a = a + a++ + ++a  <=> 14

Ами втория вариант връща при мен 15, а не 14. Което затвърждава моята теза :)
Титла: Re:Една задачка - закачка!
Публикувано от: Beginner в 19.01.2011, 17:32:44
Иначе разликите се получават не заради разликата в приоритетите на операциите, а просто в начина, по който се модифицират променливите.
Как би обяснил тогава:
а += а++ + ++а   <=> 16
a = a + a++ + ++a  <=> 14

Ами втория вариант връща при мен 15, а не 14. Което затвърждава моята теза :)
Приоритетът на операциите определя начина на модификация на променливите:
postfix-increment/prefix-increment има по-висок приоритет. Също така има значение и асоциативността на операторите
Събирането например е ляво-асоциативна операция, докато prefix-a e дясно.

Разликата идва от това че += е дясно-асоциативна операция а = е ляво-асоциативна (http://cs.smu.ca/~porter/csc/ref/cpp_operators.html)
Титла: Re:Една задачка - закачка!
Публикувано от: А.Пенев в 20.01.2011, 10:53:55
Тази дискусия според мен още веднъж показва защо тези оператори трябва да се забранят със закон  :wink:

Който иска да пише неразбираеми, заплетени и не работещи програми може да се справи успешно и без тях.

Според мен тези оператори са артефакти от древното минало, когато един байт по-малко в сорс-кода е бил от значение и хората не са могли да си направят като хората компилатора да оптимизира в тези случаи (те и сега май още не могат  :wink: )
Титла: Re:Една задачка - закачка!
Публикувано от: Светослав Енков в 20.01.2011, 11:31:57
Да, аз ги избягвам наистина тези оператори, защото не опростяват нищо и не се ускоряват програмите. Новите компилатори оптимизират доста, повече отколкото съм мислел дори, но и новите процесори са 'манджа с грозде' с тия виртуални инструкции (CISC to RISC conversion, Out-of-order execution, Hyper-Threading), така че няма смисъл, освен в краен брой много редки случаи - драйвери, обработки на изображения и критични Real-Time приложения, където пък не се използват х86 по принцип.

За задачка-закачка си са супер, да! За реална работа - не!