Форум » Синтаксис языка » Вопрос по задаче 14 » Ответить

Вопрос по задаче 14

Homosapien$: Объясните пжл. не понимаю. в задаче 14 из учебника при работе оператора for (ниже скопироавал пример из учебника) на этапе сравнения s и S и выборе большего значение. откуда берется значение S с которым нужно сравнить s. если до этого значение S нигде не вычеслялось и не назначалось? Возможно я что-то упустил. //-------------------------------------------------------------------- // rectangle.mq4 // Предназначен для использования в качестве примера в учебнике MQL4. //-------------------------------------------------------------------- int start() // Специальная функция start() { //-------------------------------------------------------------------- int L=1000, // Заданная длина нити A, // Первая сторона прямоугольн. B, // Вторая сторона прямоугольн. S, // Площадь прямоугольника a,b,s; // Текущие значения //-------------------------------------------------------------------- for(a=1; a<L/2; a++) // Заголовок оператора цикла { // Скобка начала тела цикла b=(L/2) - a; // Текущее значение сторон s=a * b; // Текущее значение площади if (s<=S) // Выбираем большее значение break; // Выходим за пределы цикла A=a; // Запоминаем лучшее значение B=b; // Запоминаем лучшее значение S=s; // Запоминаем лучшее значение } // Скобка конца тела цикла //-------------------------------------------------------------------- Alert("Максимальная площадь = ",S," A=",A," B=",B);// Сообщение return; // Оператор выхода из функции } //--------------------------------------------------------------------

Ответов - 6

SK: Homosapien$ пишет: откуда берется значение S с которым нужно сравнить s. если до этого значение S нигде не вычеслялось и не назначалось? Возможно я что-то упустил. Любая переменная - это всего лишь название некоторого значения. Значение присутствует в программе более фундаментально; можно сказать, значения имеются всегда. Значения, которые никак не назвали, существуют сами по себе; в программе их называют константами. Значения, которые как-то названы, представляют из себя содержание переменных. Поэтому у любой переменной с самого первого её упоминания в программе есть значение. Следующие записи идентичны: int S = 0; int S; Формально-бюрократически эти записи читаются так: вычислить выражение справа от знака равенства и полученное значение присвоить переменной слева от знака равенства. В первой строке справа от = явно указан 0. Вот, он и присваивается переменной S. Во второй строке нет знака равенства (и справа от него ничего не указано). Такая запись допускается. В этом случае переменная типа int инициализируется нулём (инициализируется - это значит, впервые обретает некоторое значение; в дальнейшем это значение переменной может быть изменено). В нашей программе указана строка: int L=1000, A, B, S, a,b,s; Такая запись тоже допускается. Здесь через запятую перечислены переменные, которые будут использоваться в программе как переменные целого типа (в начале строки указан int, значит эти переменные - целого типа). В данной строке переменная L инициализируется значением 1000, а все остальные переменные инициализируются нулём. Вообще, нужно сказать, что в подобных случаях разные языки диктуют разные правила. И никак интуитивно это не узнать. Поэтому в общем случае (чтоб ни у кого не спрашивать и не ошибиться) нужно запросить вывод значения переменной в нужном месте программы. Сделать это легче всего с помощью оператора Alert().В данном случае для наглядности можно вставить в программу следующий фрагмент кода: Alert("s = ", s, " S = ", S); // Выводим значения переменных s и S. перед тем местом, где значения этих переменных сравниваются: ... b=(L/2) - a; // Текущее значение сторон s=a * b; // Текущее значение площади Alert("s = ", s, " S = ", S); // Выводим значения переменных s и S. if (s<=S) // Выбираем большее значение break; // Выходим за пределы цикла ...

Homosapien$: Отлично, спасибо, что нашли время ответить. С начальным значением int S я разобрался. Тогда еще вопрос. В этом коде при итерациях происходит пересчет значения s и последующее сравнение с S. При первом расчете полученное значение s сравнивается с 0, поскольку S по умолчанию равно 0. Что просиходит при вотором расчете? Очевидно, что на каком то этапе значению S должно быть присвоено значение s из первого расчета. в коде этого присвоения не видно? Или тут какая-то другая логика? Спасибо.

SK: Наверное, Вам имеет смысл перечитать этот параграф. При втором расчёте всё так же очевидно (по ходу рассуждений смотрите на картинку 44). Значение s сравнивается с S. И если текущее значение s (то, что правее предыдущего на кривой графика) больше, чем ранее запомненное значение переменной S, значит расчёт пока ведётся в промежутке кривой слева от перегиба (экстремума, который нас-то и интересует). И так продолжается долго (с шагом в 1 мм), а именно, до тех пор, пока всё ещё не соблюдается условие (s<=S). При этом специальный выход из цикла не происходит, а в теле цикла запоминается вновь достигнутое (большее на этом интервале) значение переменной s, - оно и присваивается переменной S. Но как только мы пройдём экстремум (т.е. вычисления будут вестись уже справа от точки перегиба), то тут же окажется, что вновь вычисленное значение переменной s меньше, чем последнее запомненное значение в переменную S. Это-то и есть искомая ситуация, которая нам и указывает на необходимость прекратить расчёты в теле цикла и закончить исполнение программы в целом. В этом случае выход из цикла происходит с помощью оператора break. И программа заканчивает вычисления. В общем случае исследуемая функция может иметь несколько или множество экстремумов (как в периодических функциях, - например, sin), либо не иметь экстремума. В каждом конкретном случае нужно принимать свои меры, отдавая себе отчёт с чем имеем дело. В данном случае в рассуждениях необходимо опираться на кривую на Рис. 44. То, что кривая имеет экстремум не очевидно обычному читателю, поэтому я и дал рисунок 44 в тексте. Рассуждения здесь простые - по мере увеличения значения переменной а значение площади растёт в промежутке от 0 до экстремума, потом падает. Как только начало падать, так сразу break, которому и посвящён параграф. (я не всегда могу ответить на вопросы пользователей сразу, но отвечаю обязательно; если будут вопросы, задавайте, это нормальный процесс)


Homosapien$: спасибо за терпение. :) самое удивительное, что всю логику расчетов без привязки к коду я прекрасно понимаю - она не сложная: проверять площадь с шагом 1 пока она не начнет убывать, как только начала убывать - break. Перечитал параграф еще раз 10 :). Все равно не догоняю, с моей точки зрения не хватает одной операции присвоения. Смотрите, где я не прав?: 1-ый расчет: а=1, b=499, s=499 сравниваем s и S т.е. 499<=0 - "ложь", продолжаем расчет. 2-ой расчет: а=2, b= 498, s= 996 мы должны сравнить s и S, т.е. 996 и 499. Вот тут у меня и возникает вопрос: С какого перепугу S получила значение 499, если в предыдущем расчете S имела значчение 0? Нигде в коде переменной S не присваивается значение s. С моей точки зрения код должен выглядеть так: for(a=1; a<L/2; a++) // Заголовок оператора цикла { b=(L/2) - a; // Текущее значение сторон s=a * b; // Текущее значение площади if { s<=S // Выбираем большее значение break; }else // если в предыдущем расчете ложь, то { S=s; // присваивем переменно S значение s и возвращаемся к циклу. } } я пробовал скомпелировать свой вариант - не получается :( а ваш работает.

Homosapien$: Вы знаете , видимо я пока писал, разобрался. в коде есть присвоение S=s, я считал, что функция присвоения не включается пока не закончился цикл, получается, что при каждом расчете происходит присвоение. Извините за отнятое время. Грызу дальше :)

SK: Да. Здесь такое: в операторе if нет части else. Это значит, что если условие не выполняется, т.е. пока ещё не break, то исполнение оператора if заканчивается и управление просто передаётся оператору, следующему за if . А там несколько строк, где запоминаются последние вычисленные данные, - этот наборчик значений а и b характеризует лучшее их сочетание в смысле наибольшего S среди проверенных : ) А дальше просто. Рано или поздно в переборе найдётся такое s, которое меньше S и мы тут же break, т.е. правую ветку кривули проверять не будем, - незачем, здесь это важно. Вот и польза от применения break, о котором параграф.



полная версия страницы