Программирование на visual basic
Скачать 1.19 Mb.
|
7.2. Задачи на циклические алгоритмы Циклом – называется многократное выполнение одних и тех же дейст- вий при разном значении параметров цикла. 7.2.1. Арифметическая прогрессия 7.2.1. В первый столбец рабочего листа вывести последовательность чисел 1, 2 ,3,….,100. Решение. Выделяем рабочий лист с именем Лист1. Организуем цикл For с параметром цикла i. Параметр цикла i меняется от 1 до 100 с шагом 1. И на каждой итерации цикла в ячейку рабочего листа, стоящей в i-той строке и 1-ом столбце, записываем число i. Sub АрифметическаяПрогрессия1() Dim i As Long Sheets("Лист1").Select ' Выделяем рабочий лист с именем Лист1 For i = 1 To 100 Cells(i, 1) = i ' Записываем числа в i-тую строку первого столбца Next i End Sub 7.2.2. Во второй столбец рабочего листа вывести последовательность чисел 0, 10, 20 ,30,….,100. Sub АрифметическаяПрогрессия() Dim i As Long Sheets("Лист1").Select For i = 1 To 11 Cells(i, 2) = 10*(i-1) Next i End Sub 7.2.3. В третий столбец рабочего листа вывести последовательность чи- сел -20, 20, 60, … , 500, 540. Sub АрифметическаяПрогрессия3() Dim i As Long Sheets("Лист1").Select For i = 1 To 15 Cells(i, 3) = -20 + 40 * (i - 1) Next i End Sub 7.2.4. В четвертый столбец рабочего листа вывести последовательность чисел 10, -30, -70, …, -710, -750. 82 Sub АрифметическаяПрогрессия4() Dim i As Long Sheets("Лист1").Select For i = 1 To 20 Cells(i, 4) = 10 - 40 * (i - 1) Next i End Sub 7.2.5. В пятый столбец рабочего листа вывести последовательность чи- сел 10, 30, 60, 0, 110, -30, …, 410, -210, 460, -240. Решение. Нетруднозаметить, что здесь вперемежку записаны две арифметические прогрессии 10, 60, 110, … , 410,460 и 30, 0, -30, …, -210, - 240. Поэтому в нечетные строки пятого столбца пишем элементы первой прогрессии, а в четные – второй прогрессии. Sub АрифметическиеПрогрессии5() Dim i As Long Sheets("Лист1").Select 'Тело цикла выполняется 11 раз. При i=1, 3, 5, 7, 9, 11, 13, 15, 17, 19. For i = 1 To 20 Step 2 ' В нечетные строки пишем члены первой последовательности Cells(i, 5) = 10 + 50 * (i - 1) \ 2 ' В четные строки пишем члены второй последовательности Cells(i + 1, 5) = 30 - 30 * (i - 1) \ 2 Next i End Sub 7.2.2. Геометрическая прогрессия 7.2.6. В первый столбец рабочего листа Лист2 вывести последователь- ность чисел 1, 2, 4, …, 1024, 16384, 32768. Решение. Это геометрическая прогрессия со знаменателем, равным 2, и первым элементом, равным 1. Здесь 11 членов последовательности. Чтобы получить очередной член прогрессии, необходимо текущий умножить на 2. В приведенной программе в качестве текущего члена прогрессии высту- пает переменная b. Sub ГеометрическаяПрогрессия1() Dim i As Integer, b As Integer Sheets("Лист2").Select b = 1 ' Первый член геометрической прогрессии ' Цикл по всем 11 членам геометрической прогрессии For i = 1 To 11 Cells(i, 1) = b ' Записать в ячейку b = b * 2 'Получить следующий член геометрической прогрессии Next i End Sub Внимание. Если по данной программе мы попытаемся получить 15 членов данной прогрессии, заменив конечное значение параметра цикла 11 83 на число 15, то произойдет ошибка выполнения программы – переполне- ние. Так как при i=15 будет выведено число b=16384, а при умножении b*2 должно получиться число 32768, которое превышает максимально воз- можное число типа Integer. В этом случае необходимо для переменной b использовать тип Long. 7.2.7. Во второй столбец рабочего листа Лист2 вывести последователь- ность чисел 2, -4, 8. …, 1024, -16384, 32768. Решение. Это также геометрическая прогрессия со знаменателем, рав- ным –2, и первым членом прогрессии, равным 2. Sub ГеометрическаяПрогрессия2() Dim i As Integer, a As Long Sheets("Лист2").Select a = 2 ' Общий член геометрической прогрессии For i = 1 To 15 Cells(i, 2) = a a = -a * 2 'Получить следующий член геометрической прогрессии Next i End Sub 7.2.8. В третий столбец рабочего листа Лист2 вывести последователь- ность из 100 чисел , 1, 2, 0.5, 6, 0.25, 18, … Решение. Эта числовая последовательность состоит из двух геометри- ческих прогрессий. Первая прогрессия имеет первый член, равный 1, и знаменатель 0.5. Вторая прогрессия имеет первый член, равный 2, и знаме- натель 3. Sub ГеометрическаяПрогрессия3() Dim i As Integer, b As Double, a As Double Sheets("Лист2").Select a = 1: b = 2 For i = 1 To 50 Step 2 Cells(i, 3) = a Cells(i + 1, 3) = b a = a * 0.5: b = b * 3 Next i End Sub 7.2.3. Вычисление суммы арифметической последовательности Вычисление суммы N слагаемых производится по следующему алго- ритму: 1) для значения суммы отводится переменная типа соответствующего типу слагаемых. Обнуляется значение этой переменной. Иногда сумме присваивается значение первого слагаемого; 2) организуется цикл при помощи операторов цикла. Внутри тела цик- ла вычисляется значение очередного слагаемого, которое затем на- капливается в переменной, соответствующей сумме последовательности. 84 7.2.9. Найти сумму 10 слагаемых действительного типа, значения кото- рых вводятся с клавиатуры. Sub СуммаЧисловойПоследовательности1() Const N = 10 Dim s As Double, i As Long, a As Double s = 0 ' Переменная, в которой накапливаем значения суммы For i = 1 To N a = CDbl(InputBox("Введите " + Str(i) + "-ое слагаемое")) s = s + a ' Накопление очередного слагаемого Next i MsgBox ("Сумма = " & s) ' Вывод результата End Sub 7.2.10. Найти сумму 100 слагаемых действительного типа Решение. В развернутом виде эта сумма представляется в виде 100 сла- гаемых: S=2/8 + 3/18 + 4/42 + 5/86 + 6/156 + 7/258 + 8/398 + … + 101/ 1010006. Sub СуммаЧисловойПоследовательности2() Dim S As Double, n As Long ‘ Обнулить переменную, в которой будет накапливаться сумма S = 0 For n = 1 To 100 ‘ Накопить в переменной S очередное n-ное слагаемое S = S +( n+1) / (n ^ 3 + n ^ 2 + 6) Next n ‘ Вывести переменную S. После запятой выводить четыре знака. Debug.Print "Сумма = "; format(S,”#0.0000”) End Sub Ответ: Сумма = 0,7785. 7.2.11. Найти сумму 100 слагаемых действительного типа Решение. Знаки слагаемых этой суммы чередуются. Знак первого сла- гаемого ─ плюс; второго –– минус; третьего –– плюс; и т.д. Для знака вве- дем переменную z. Присвоим ей начальное значение –1, а после накопле- ния суммы изменяем знак оператором z=-z. 6 1 100 1 2 3 ∑ = + + + = n n n n S 6 ) 1 ( 100 1 2 ∑ = + + − n n n n n 85 ∑ = = 20 1 2 n n S ∑ = = 100 1 ! 2 n n n S Sub СуммаЧисловойПоследовательности3() Dim S As Double, n As Long, Z as Integer S = 0 ' В этой переменной накапливается сумма слагаемый Z=-1 ' В этой переменной хранится знак очередного слагаемого For n = 1 To 100 S = S +Z*( n+1) / (n ^ 3 + n ^ 2 + 6) Z=-Z ' Изменить знак слагаемого Next n Debug.Print "Сумма = "; format(S,”#0.0000”) End Sub Ответ: Сумма = -0,1431. 7.2.4. Сумма индуктивных слагаемых Слагаемые называются индуктивными, если следующее слагаемое по- лучается как функция текущего слагаемого. 7.2.12. Найти сумму 20 слагаемых действительного типа: В развернутом виде эта сумма представляется в виде 20 слагаемых: В качестве текущего слагаемого выберем переменную типа Long, имеющую идентификатор a . Перед циклом присвоим переменной a на- чальное значение, совпадающее с первым слагаемым. В переменной S бу- дем накапливать сумму. Начальное значение S= a . Для вычисления суммы остальных 19 слагаемых применяем оператор цикла с параметром цикла n , меняющимся от 2 до 20 с шагом 1. Внутри цикла получаем очередное сла- гаемое, умножая предыдущее значение на 2, и накапливаем полученное слагаемое в переменной S. Sub СуммаИндуктивнойПоследовательности1() Dim S As Long, n As Long, a As Long a = 2: S = a For n = 2 To 20 a = a * 2 ' Очередное слагаемое S = S + a ' Накопление суммы Next n Debug.Print "Сумма = "; Format(S, "#,##0") End Sub Ответ: Сумма = 2 097 150. 7.2.13. Найти сумму 100 слагаемых действительного типа Решение. Функция n! =1· 2 · 3· 4· …· n представляет собой произ- 2 2 2 2 20 3 2 + + + + = S 86 ведение первых n чисел натурального ряда. В развернутом виде эта сумма представляется в виде 100 слагаемых: Введем две переменные типа Double a – общий член этой суммы и S – сумма. Перед циклом этим переменным присвоим начальные значения, равные первому слагаемому: a=2, S=2. Чтобы получить следующее слагае- мое, необходимо текущее слагаемое умножить на 2 и разделить на номер следующего слагаемого. Sub СуммаИндуктивнойПоследовательности2() Dim S As Double, n As Long, a As Double a = 2: S = 2 For n = 2 To 100 a = a * 2 / n ' Получить очередное слагаемое S = S + a ' Накопить его в переменной S Next n Debug.Print "Сумма = "; Format(S, "#.00000000") End Sub Ответ: Сумма = 6,38905610. Ответ выведен с точностью восьми знаков после запятой. Нетрудно за- метить, что слагаемые данной суммы уменьшаются. Если перед операто- ром Next n вставить оператор Debug.Print Format(a,"#.00000000") для вы- вода слагаемых a с точностью 8 знаков после запятой , то получим сле- дующие результаты: 2,00000000 1,33333333 ,66666667 ,26666667 ,08888889 ,02539683 ,00634921 ,00141093 ,00028219 ,00005131 ,00000855 ,00000132 ,00000019 ,00000003 ,00000000 Остальные слагаемые равны 0. Так как функция N! быстро возрастает, слагаемые быстро убывают, и уже 16 слагаемое при суммировании можно не учитывать. Программу можно модифицировать, используя оператор цикла While. Sub СуммаИндуктивнойПоследовательности3() Dim S As Double, n As Long, a As Double a = 2: S = 2: n = 1 ' Выполнять цикл пока a> 0.00000001 While a > 0.00000001 n = n + 1: a = a * 2 / n: S = S + a Wend Debug.Print "Сумма = "; Format(S, "#.00000000"); ", n="; n End Sub Ответ: Сумма = 6,38905610, n= 16. 7.2.14. Найти сумму 100 слагаемых действительного типа 100 99 3 2 1 2 99 3 2 1 2 3 2 1 2 2 1 2 1 2 100 99 3 2 ⋅ ⋅ ⋅ ⋅ ⋅ + ⋅ ⋅ ⋅ ⋅ + + ⋅ ⋅ + ⋅ + = … … … S 87 Решение. В развернутом виде эта сумма представляется в виде : Чтобы получить следующее слагаемое, необходимо текущее слагаемое умножить на –1 и разделить на произведение двух целых чисел (2n-1)2n, где n – номер слагаемого. Слагаемые этой суммы очень быстро убывают. Так как часть слагаемых отрицательна, в условии выхода из цикла исполь- зуется функция вычисления модуля числа Abs. Sub СуммаИндуктивнойПоследовательности4() Dim S As Double, n As Long, a As Double a = -0.5: S = a: n = 1 Do Debug.Print Format(a, "#.00000000"); " "; n = n + 1: a = -a / ((2 * n - 1) * 2 * n): S = S + a Loop While Abs(a) > 0.00000001 Debug.Print Format(a, "#.00000000") Debug.Print "Сумма = "; Format(S, "#.00000000"); ", n="; n End Sub Ответ: -,50000000 ,04166667 -,00138889 ,00002480 -,00000028 ,00000000 Сумма = -,45969769, n= 6. 7.3. Задачи на разветвляющиеся алгоритмы Алгоритмы называются разветвляющимися, если в произвольной точке программы в зависимости от выполнения или невыполнения некоторых условий происходит переход управления в разные точки программы. В разветвляющихся алгоритмах применяются операторы if , select и goto 7.3.1. Вычислить значение числа k. Sub Ветвление1() ∑ ∞ = − = 1 )! 2 ( ) 1 ( n n n S 8 7 6 5 4 3 2 1 1 6 5 4 3 2 1 1 4 3 2 1 1 2 1 1 … − ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ + ⋅ ⋅ ⋅ ⋅ ⋅ − ⋅ ⋅ ⋅ + ⋅ − = S ⎪⎩ ⎪ ⎨ ⎧ ≤ + > + = ⎟ ⎠ ⎞ ⎜ ⎝ ⎛ = − = − 15 21 , 21 15 ; 3 1 100 ; 4 2 1 5 0 75 0 2 2 2 2 2 lg 9 ln 2 1 3 b a при b a b a при b a k tg b a 88 Dim a As Double, b As Double, k As Double a = 0.75 * Sqr(0.5) - 1 / 2 * 4 ^ (1 / 3) b = 100 ^ (1 / 2 * Log(9) - Log(2) / Log(10)) * Tan(1 / 3) If a > b Then k = Sqr(15 * a ^ 2 + 21 * b ^ 2) Else _ k = Sqr(21 * a ^ 2 + 15 * b ^ 2) Debug.Print "a= "; a; "; b= "; b; "; k= "; k; ”.” End Sub Ответ: a= -0,263370440094189; b= 13,6319762297472; k= 52,8102100231471. 7.3.2. Вычислить значение функции Sub ПримерНаСоставнойIf() Dim x As Double x = CDbl(InputBox("Введите значение аргумента функции")) Debug.Print "Значение функции= "; Funct1(x) End Sub Function Funct1(x As Double) As Double Dim y As Double If x <= 0 Or x > Sqr(2) Then y = 0 ElseIf x <= 1 Then y = x ^ 2 Else: y = 2 - x ^ 2 End If Funct1 = y End Function 7.3.3. По введенному номеру месяца вывести количество дней в этом месяце, название месяца и название сезона. Sub ЧислоДнейНазваниеМесяцаСезона() Dim Month As String, Days As Integer, Season As String, Ye As Integer Dim NumbM As Integer beg: NumbM = Val(InputBox("Введите номер месяца")) If NumbM < 1 Or NumbM > 12 Then MsgBox ("Ошибочно введен номер месяца. Повторите ввод!") GoTo beg End If ' Определение числа дней в месяце Days = 31 If NumbM = 4 Or NumbM = 6 Or NumbM = 9 Or NumbM = 11 Then _ Days = 30 ⎪ ⎪ ⎩ ⎪⎪ ⎨ ⎧ ∞ ∈ ∈ − ∈ −∞ ∈ = ) ; 2 ( 0 ] 2 ; 1 ( , 2 ] 1 ; 0 ( , ] 0 ; ( , 0 ) ( 2 2 x x x x x x x F 89 If NumbM = 2 Then Days = 28 Ye = Val(InputBox("Введите год")) ' Если год високосный и месяц Февраль If (Ye Mod 4) = 0 Then Days = 29 End If ' Определение название месяца Dim NameMonth As Variant NameMonth = Array("Январь", "Февраль", "Март", "Апрель", "Май", _ "Июнь", "Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь") Month = NameMonth(NumbM) ' название месяца ' Определение название сезона, к которому относится месяц Select Case NumbM Case 12, 1, 2 Season = "Зима" Case 3 To 5 Season = "Весна" Case 6 To 8 Season = "Лето" Case 9 To 11 Season = "Осень" End Select MsgBox ("Месяц номер" + Str(NumbM) + " называется" + _ Month +Chr(13)+ " содержит "+Str(Days)+"дней"+ Chr(13) + _ " и относится к сезону " + Season) End Sub 7.3.4. По введенному номеру дня, месяца и года вывести номер, месяц и год предыдущего дня. Sub ВчерашнийДень() Dim Day As Integer, Month As Integer, Year As Integer, _ NameMonth As Variant NameMonth = Array("Январь", "Февраль", "Март", "Апрель", "Май", _ "Июнь", "Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", _ "Декабрь") Day = Val(InputBox("Введите день")) Month = Val(InputBox("Введите номер месяца")) Year = Val(InputBox("Введите год")) Day = Day - 1 If Day = 0 Then Month = Month - 1 If Month = 0 Then Year = Year - 1: Month = 12 End If Select Case Month Case 1, 3, 5, 7, 8, 10, 12 Day = 31 Case 4, 6, 9, 11 90 Day = 30 Case 2 If (Year Mod 4) = 0 Then Day = 29 Else Day = 28 End Select End If MsgBox ("Вчера было " + Str(Day) + " " + NameMonth(Month) + _ " Год " + Str(Year)) End Sub 8. Задачи сортировки Задача сортировки элементов массивов является одной из наиболее важных и популярных задач для компьютеров. Во многих вычислительных системах на нее уходит более половины вычислительного времени. По- пробуйте в не отсортированном списке учеников школы или института найти свою фамилию. Для этого Вы должны внимательно прочитать спи- сок от начала до нужной фамилии, что займет значительное время. А в списке, написанном по алфавиту, Вы быстро подойдете к необходимому листу и найдете Вашу фамилию. 8.1. Перестановка элементов в массиве При решении задач сортировки постоянно необходимо решать более простые задачи: • находить в массиве наибольший или наименьший элемент; • менять местами два элемента. 8.1.1. Найти наименьшее значение среди 20 введенных с клавиатуры вещественных чисел и указать, на каком месте оно находится. Sub МинимальноеИз20Чисел() Const n = 20 Dim numb As Double, min As Double, i As Long, imin As Long min = 1.7E+308 ' Это +∞ imin = 0 ' Номер минимального числа For i = 1 To n numb = CDbl(InputBox("Введите " + Str(i) + "-ое число")) ' Если введено число меньшее, чем все предыдущие, то ‘ запомнить новое минимальное значение и его номер ' Здесь оба оператора присваивания выполняются, только ‘ если numb If numb < min Then min = numb: imin = i Next i MsgBox ("Минимальное из введенных чисел =" + Str(min) + Chr(13) _ + "это число номер " + Str(imin)) End Sub 8.1.2. В последовательности вещественных чисел, находящихся в столбце |