Добро пожаловать в Engee
Программирование
Цель: Научиться писать алгоритмы, выполняющие инструкции в соответствии с набором условий.
Вводное видео
Транскрипция видео
Все скрипты, которые мы до сих пор разрабатывали, выполняют команды в заданном порядке, от начала до конца. Но как быть в случае, если вы хотите рассчитывать квадратный корень только для положительных аргументов? Вы можете удалить эти строки, когда x – отрицательное число. Но тогда вам придётся возвращать их вручную, если попадется положительный x. Конечно, в самом коде можно определять условие выполнения, в зависимости от значения x – положительное или отрицательное, и соответствующим образом менять цепочку принятия решений. Если значение x положительное, то условие вычисляется как истина, и код будет выполнен целиком. А если значение x отрицательное, то условие вычистится как ложь и эта строка будет пропущена. Слово if – один из важных способов управления выполнением скрипта. Конструкции if-else в разных случаях дают управление разным отрезкам кода (их может быть и больше, чем два).
Бывает что нужно не пропустить некоторый код, а многократно его повторить. Можно начать копировать, вставлять и изменять строчки кода, ну... это хороший повод применить цикл for. Этот наиболее часто использующийся вид циклов. Строки кода, записанные в теле цикла, выполняются несколько раз. При первом проходе по циклу значение x равно 1. Во время второго прохода значение x равно 2 и так далее. При каждом проходе x меняет значение, пробегая по всем элементам диапазона или вектора. Как только x будет равен последнему значению в диапазоне, цикл выполнится в последний раз для последнего входного значения и скрипт продолжит выполняться после инструкции end.
Если ваш код очень простой, как, например, расчет квадрата нескольких чисел, то, наверное, вам не понадобятся циклы. Многие операции можно провести сразу над всем вектором или матрицей. Таким образом, код будет чище и лаконичнее, ведь не придется писать лишний цикл for. А в тех случаях, когда код посложнее, цикл for отлично помогает выполнить набор задач, перебирая по очереди разные входные данные.
Упражнение 1: Описываем условия выполнения кода
Код внутри блока if (если), называемый телом блока, выполняется только в том случае, если условие блока принимет значение истина (true).
В условии можно использовать любые выражения, но самое простое – проверить два объекта на равенство друг другу при помощи оператора ==.
if x == 0.5
y = 3
end
using CSV, DataFrames, Plots, LaTeXStrings, Statistics;
cd(@__DIR__);
default(fmt = :png); # Все графики должны иметь формат PNG
data = CSV.read("data_only.csv", DataFrame, header=0);
element = CSV.read("elements_only.csv", DataFrame, header=0);
density = data[:,1];
display(data)
doPlot = rand(0:1) # С помощью этой переменной мы внесём лёгкую непредсказуемость в работу условного оператора
Задача 1
plot(density, label="Эксперимент 1", legend = :outerright)
xticks!(1:length(density), dropdims(Array(element), dims = 2))
title!("Замеры образцов")
ylabel!( L"Плотность (г/см^3)" )
выполнялись только тогда, когда значение переменной doPlot равно 1.
#
plot(density, label="Эксперимент 1", legend = :outerright)
xticks!(1:length(density), dropdims(Array(element), dims = 2))
title!("Замеры образцов")
ylabel!( L"Плотность (г/см^3)" )
#
Подсказка
Добавьте инструкции if и end как в следующем примере:
if doPlot == 1
# *Код вывода графика;*
end
Решение
if doPlot == 1
plot(density, label="Эксперимент 1", legend = :outerright)
xticks!(1:length(density), dropdims(Array(element), dims = 2))
title!("Замеры образцов")
ylabel!( L"Плотность (г/см^3)" )
end
Задача 2
Вполне возможно, что вам нужно будет предусмотреть особенный набор команд на тот случай, если условие не выполняется. Чтобы это реализовать, нужно добавить в условную конструкцию второй блок кода, отделенный ключевым словом else (иначе). Например, как здесь:
x = rand()
if x > 0.5
y = 3
else
y = 4
end
else должен будет привести к выполнению следующей строчки:
join(stdout, Array(string.("Образец ", element, ": плотность ", density)), '\n' )
Подсказка
Добавьте перед инструкцией end новую инструкцию else и второй строкой после else поместите указанную строчку кода. Остальной код остается прежним.
Решение
if doPlot == 1
plot(density, label="Эксперимент 1", legend = :outerright)
xticks!(1:length(density), dropdims(Array(element), dims = 2))
title!("Замеры образцов")
ylabel!( L"Плотность (г/см^3)" )
else
join( stdout, Array(string.("Образец ", element, ": плотность ", density)), '\n' )
end
Задача 3*
Попробуйте несколько раз выполнить код, начиная с той ячейки, где устанавливается переменная doPlot, чтобы проверить поведение условной конструкции в разных сценариях.
Еще одна инструкция условного блока elseif может быть использована после if для описания дополнительных условий для выполнения следующих блоков кода. В одной условной конструкции может быть несколько блоков elseif.
if условие1
код
elseif условие2
код
end
Предлагаем попробовать создать еще одну случайную переменную doDisplay, чтобы управлять отображением значений плотности на графике. Цель в том, чтобы добавить в каждом случае новое вложенное условие elseif, при котором к графику добавятся аннотации точек:
annotate!(1:length(density), density, string.(density), :bottom)
а текстовый вывод будет выглядеть следующим образом:
join(stdout, Array(string.("Образец ", element)), '\n' )
Что происходит с выводом, если обе переменные doPlot и doDisplay равны 1? Что случится если они обе равны 0 или только doDisplay равен 1?
Упражнение 2: Создаем повторяющиеся циклы в коде
При запуске кода на иллюстрации тело цикла будет выполнено три раза, пока счетчик цикла (c) не дойдет от первого значения диапазона 1:3 до последнего, пройдя значения 1, 2, и 3.
Задача 1
n раз. Нужный код расположен между знаками комментариев #.
Переменная счетчика должна называться idx. При первом выполнении цикла переменная idx должна быть равна 1. С каждым новым шагом цикла ее значение должно увеличиваться на 1.
n = 100
x = zeros(n);
y = zeros(n);
plot()
#
x[idx] = rand()
y[idx] = rand()
scatter!( [Statistics.mean(x[1:idx])], [Statistics.mean(y[1:idx])],
markershape=:circle, label="",
palette = :summer, colorIndex=idx/n, markerstrokewidth=0.1 )
#
plot!(title="Накопленная статистика ряда чисел\nсходится к x,y = (0.5,0.5)")
Подсказка
Цикл for должен использовать переменную idx в качестве счетчика.
for idx = 1:n
...
end
Измените скрипт таким образом, чтобы весь код между знаками # располагался внутри цикла, между for и end.
Решение
n = 100
x = zeros(n);
y = zeros(n);
plot()
for idx = 1:n
x[idx] = rand()
y[idx] = rand()
scatter!( [Statistics.mean(x[1:idx])], [Statistics.mean(y[1:idx])],
markershape=:circle, label="",
palette = :summer, colorIndex=idx/n, markerstrokewidth=0.1 )
end
plot!(title="Накопленная статистика ряда чисел\nсходится к x,y = (0.5,0.5)")