Решаване на задачи с едномерни масиви



Pdf просмотр
Дата18.12.2022
Размер1.51 Mb.
#115945
ТипЗадача
vektori


1
VBAps5: РЕШАВАНЕ НА ЗАДАЧИ С ЕДНОМЕРНИ МАСИВИ
(ВЕКТОРИ)
Условие на задача с едномерни масиви (вектори) В настоящото упражнение ще се запознаете с някои от формулите и алгоритмите, като например формулите за намиране на средно-аритметична стойности на скаларно произведение и алгоритмите за намиране на екстремум (максимум или минимуми за сортиране, които представляват същността на всеки уводен курс по Програмиране и са полезни при решаването на почти всички курсови задачи. Условието на задачата която трябва да се реши в настоящото упражнение е следното Даден е едномерен масив (вектор) A(n) с реални елементи.
1. Размерът на вектора и стойностите на елементите му да се въведат от текстов файл със следната структура n
A
1
A
2
… Въведените стойности на елементите на вектора да се изведат контролно нас точност два знака след десетичната точка във вида Вектор АДа се намери и изведена броят на положителните елементи във вектор A.
3. Да се намери и изведена максималният по стойност елемент на вектор A.
4. От клавиатурата да се въведе стойност за константа C. Да се състави вектор B, чиито елементи представляват стойностите на всеки елемент от вектор A умножен по C. Вектор B да се изведена по същия начин както вектор A.
5. Вектор A да се сортира по стойност в нарастващ реди да се изведена. Да се намери и изведена скаларното произведение на векторите A и B.
7. Да се намери и изведена средно-аритметичната стойностна елементите във вектор B. Решението на отделните части на задачата да стане в подпрограми. На базата на решенията на подусловия 2, 3 и 5, студентите самостоятелно трябва да напишат подпрограми решаващи следните задачи
8. (а) Да се намери и изведена броят на отрицателните елементи във вектора) Да се намери и изведена минималният по стойност елемент на вектора) Вектор B да се сортира по стойност в намаляващ реди да се изведена. Въвеждане и контролно извеждане на елементите на вектора
За начало, трябва да създадете и запишете текстов файл с размера и стойностите на елементите на вектор A. За тази цел трябва да отворите приложението Notepad. Ако стена компютър с операционна система Windows XP, натиснете бутона Start в долния ляв ъгълна екрана, в излезлия списък изберете Programs, след това Accessories и накрая
Notepad. Ако стена компютър с по-нова версия на Windows, от клавиатурата натиснете клавишите с логото на Windows и на буквата R едновременно, а в текстовото поле на


2 диалоговия прозорец Run напишете Notepad; натиснете OK. (За създаването на файл с разширение *.txt, каквито прави и Notepad, може също да използвате приложението
Word, и при записването на файла, отпадащия списък вдясно от текста Save as type: да изберете опцията Plain Text.) В съответствие с условието, на първия ред в работното пространство на Notepad напишете цяло положително число представляващо размера - или броя елементи - в едномерния масива на следващия ред въведете стойностите на тези елементи разделени с празна позиция. Като примерно съдържание на текстовия файл може да използвате следните два реда
7 1.1 -1.2 1.3 -1.4 1.5 -1.6 1.7 След като напишете размера и стойностите на елементите на вектора, от менюто File изберете командата Save. В полето за въвеждане на имена файла вдясно от File Name: изтрийте текста *.txt и задайте имена файла, примерно vector. От списъка с дискови пространства вляво на диалоговия прозорец Save As, или отпадащия списък най-отгоре на прозореца, изберете подходящо място където да запишете текстовия файл vector.txt. Ако работите на компютър в Университетския Изчислителен Комплекс, запишете файла на диска D, ако е възможно. Във всеки случай, внимателно си отбележете на лист целия адрес, включително и името, на файла, защото скоро ще трябва да го запишете в текста на програмата. След това натиснете Save в диалоговия прозорец и затворете
Notepad от X в горния десен ъгълна приложението. Отворете нов, празен файл на Excel. В лентата Developer, натиснете най-левия бутон Visual Basic. В редактора на Visual Basic, от менюто Insert изберете командата
Module. Най-горе в отворилото се работно пространство Module1, напишете Option
Explicit, а през един ред напишете заглавния редна програма с примерно име Vector. В частта с декларации на главната програма Vector, трябва да декларирате променливите които ще използвате за трансфер на данни между отделните части на програмата. Те включват една целочислена променлива n за размерна масива, динамичен масив A с реални елементи, а за подусловия 4, 6 и 7 и друг динамичен масив B с реални елементи. Така, за начало напишете
Option Explicit
Sub Vector()
Dim n As Integer, A() As Single, B() As Single В този начален етапна писането на кода на тази сравнително сложна програма е добре да помислите как да я организирате, така чеда не се налага да пишете един и същи текст няколко пъти, ако в отделните ѝ части има повтарящи се действия. Изглежда, че първо трябва да създадете подпрограма която да въвежда входните данни от текстов файла после да ги извежда контролно на Sheet1. Тъй като няколко пъти в задачата трябва да се прави извеждане на стойностите на едномерен масив – първо на А, след това на B, а после и на сортирания в нарастващ ред векторна, ще е най-практично извеждането, което в условието е записано като част от подусловие 1, да се обособи като отделна подпрограма, която после да се вика от другите подпрограми


3 които включват извеждане на стойностите на векторна. Ако за подпрограмата въвеждаща входните данни използвате име като например InputArray( ), в главната програма може да напишете Въвеждане на вектор
Call InputArray(n, A) Подпрограмата InputArray приличана подпрограмата InpCoor, която писахте в миналото упражнение за въвеждане на координати на точки от текстов файл. И в двете програми името на текстов файл с входните данни трябва да се въведе от клавиатурата
- а най-добре е адресът и името на файла да се запишат като стойност по подразбиране, те. трети аргумент на функцията InputBox, и след това с помощта на функцията Dir( ) да се провери дали на дадения адрес има файл с въведеното име. Ако текстовият файл не се намерите. функцията Dir( ) върне празен стринг, а не адрес, име и разширение на файл съвпадащи с аргумента ѝ - изпълнението на програмата трябва да се прекрати. Иначе, ако файлът се намери, той трябва да се отвори за четене и от него подред да се прочетат стойности за размера и за елементите на вектор A. След това работният лист с име Sheet1 - или съответствието му на друг език, ако използвате преведена версия на
Excel - трябва да стане текущи на него прегледно да се изведат прочетените данни подзаглавие което описва същността на числата. Както вече беше казано, за извеждането ще е най-практично от подпрограмата InputArray да се извика друга такава, наречена примерно OutArray, която с цикъл For-Next да изведе всички стойности на елементите на конкретен вектор. Позиционирайте курсора накрая на реда със заключителния текст
End Sub заглавната програма Vector и натиснете Enter два-три пъти за да оставите празно място. После за код на InputArray напишете следното
Sub InputArray(n As Integer, A() As Single)
Dim i As Integer, FName As String
' Въвеждане на адреси имена файла с входни данни
FName = Адреси имена файл с входни данни, _
"Vector", "d:\vector.txt")
If Dir(FName) = "" Then
MsgBox (Файлът " & FName & " не е намерен !!!")
Stop
End If
Close #1
Open FName For Input As #1
' Въвежда вектор
Input #1, n
ReDim A(n)
For i = 1 To n
Input #1, A(i)
Next i


4
Close #1
' Извежда векторна, "Вектор A")
End Sub В началото на подпрограмата InputArray, на мястото на третия аргумент "d:\vector.txt" на функцията InputBox не забравяйте в кавички да напишете точните адреси имена файла с входни данни, който подготвихте и записахте в началото на упражнението. На последния ред в горния текст на тялото на подпрограмата InputArray се извиква подпрограмата OutArray за извеждане на стойностите на вектор. В списъка с аргументите, след размера и стойностите на вектора, фигурира цяло число за редна който да се изпише заглавие обясняващо какво представляват стойностите, както и самото заглавие. Това ще позволи стойностите на един или друг вектор да се изпишат на различни места на Sheet1 и под различни заглавия, което ще улесни многократното използване на подпрограмата OutArray в отделните части на програмата. Текстът нае доста кратък и приличана подпрограмата OutCoor, която писахте в миналото упражнение. Тъй като листът Sheet1 беше направен текущи клетките в него бяха изчистени в InputArray, в OutArray оставана реда записан като трети аргумент на подпрограмата да се напише и форматира заглавието получено като четвърти, текстов аргумент на OutArray, след което на следващия ред да се изведат с цикъл For-Next n наброй стойности за елементите на конкретния едномерен масив. След текста End Sub на подпрограмата InputArray, натиснете Enter два-три пъти и напишете
Sub OutArray(n As Integer, A() As Single, _ r As Integer, title As String)
Dim i As Integer
With Cells(r, 1)
.Value = title
.Font.Size = 14
.Font.Bold = True
End With
For i = 1 To n
Cells(r + 1, i).Value = A(i)
Cells(r + 1, i).NumberFormat = "0.00"
Next i
End Sub След като завършите двете подпрограми за въвеждане и извеждане на входните данни е най-добре да тествате програмата Vector. От менюто Debug изберете Compile
VBAProject. Ако Ви се струва, че е безсмислено да компилирате текста на програмата


5 при положение, че интерпретаторът вече я е проверил ред поред, имайте предвид, че интерпретаторът не проверява правописа на елементите от обектния модел на Excel. За помощ с изписването на тези думи, някои от които са много сложни, може да разчитате само на компилатора. Ако той открие синтактични грешки, отстранете ги като се съобразите с насоките в съобщенията. Позиционирайте курсора в главната програма
Vector и стартирайте програмата като натиснете бутона със зелено триъгълниче. Ако се появи диалоговият прозорец Macros за изборна програма за изпълнение, изберете
Vector и натиснете Run. В прозореца за въвеждане на имена файл с входни данни, внимателно проверете дали дадената в текстовото поле стойност отговаряна адреса и името на файла който подготвихте и записахте в началото на упражнението. Ако тя не отговаря или липсва, напишете точните адрес, име и разширение на файла с входните данни и натиснете OK. Ако отговаря, натиснете OK в диалоговия прозорец. Отидете на
Sheet1. Ако намирането на файла е минало безпроблемно, на Sheet1 трябва има Фигура 1 Извеждане на елементите на векторна с програмата Vector Намиране наброй положителни елементи
Във второто подусловие на задачата трябва да се намери и изведена броят положителни елементи във вектор A. Ще обособите решението му в нова подпрограма. За да я извикате от главната програма Vector, кликнете в края на текста на програмния ред с извикването на подпрограмата InputArray, натиснете Enter два пъти за да оставите за прегледност един празен ред преди следващото извикване и след това напишете Броене на положителни елементи
Call CountPositive(n, A, 4) В горния текст за имена подпрограмата за броене на положителни елементи на вектор
A е използвано CountPositive, а списъкът с фактическите параметри включва броя елементи, самия вектори номера на реда на който трябва да започне изписването на резултата. При определянето на този номер е взето предвид, че два реда вече са заети с първоначалното извеждане на масива и че е най-добре третият ред да остане празен за прегледност при изписването на резултатите от работата на двете подпрограми. Освен


6 това, в края на условието на задачата е отбелязано също, че на базата на кода за броене на положителните елементи във вектор А ще трябва самостоятелно да напишете друга подпрограма за броене на отрицателните елементи във вектор B, която може да се казва примерно CountNegative, така че е най-добре CountPositive да се организира така, че с копиране и минимални промени на съдържанието тя да може да се преобразува в текст на подпрограма за броене на отрицателни елементи на произволен вектор. Алгоритъмът за броене налага използването на една целочислена променлива за записване на резултата, както и на друга за управляваща променлива на цикъла в който ще се проверява дали всеки от елементите е положителен. Ако в условието на дадена задача не са споменати някакви извънредни условия, за начална стойностна броене се използва 0, тъй като е възможно да няма нито един елемент който да отговаряна критерия за броене – в настоящия случай, във вектор A може да няма нито един положителен елемент. При броенето на специфични стойности, изчислителният цикъл съдържа структура за разклонение If в чието условие се записва релационен израз описващ критерия на който трябва да отговарят елементите които се броят – в случая те трябва да са положителните. или по-големи от нула, ако нулата не се приема за положително число, или по-големи или равнина нула, ако нулата се приема за положително число. За всеки елемент който отговаряна дадения критерий, теза който резултатът от релационния израз след If е True, стойността на брояча се увеличава с единица. След намирането на търсения брой в изчислителния цикъл на подпрограмата, резултатът трябва да се изведе, за предпочитане подзаглавие обясняващо какво точно представлява намерената стойност. Ако при разглеждането на релационния израз в разклонението включено в изчислителния цикъл резултатът нито веднъж не е бил True, те. нито един елемент не е отговарял на критерия за броене, на Sheet1 ще се изпише началната стойност присвоена на променливата за броене преди влизането в цикъла, те. 0 в сегашния случай. Това означава, че във вектор A няма нито един положителен елемент. Позиционирайте курсора следна последно написаната подпрограма
OutArray и натиснете Enter два-три пъти за прегледност. За текст на CountPositive може да използвате следното
Sub CountPositive(n As Integer, A() As Single, r As Integer)
Dim cnt_Pos As Integer, i As Integer cnt_Pos = 0
For i = 1 To n
If A(i) > 0 Then cnt_Pos = cnt_Pos + 1
End If
Next i
With Cells(r, 1)
.Value = "Брой положителни елементи във вектор A"
.Font.Size = 14
.Font.Bold = True
End With


7
Cells(r + 1, 1).Value = cnt_Pos
End Sub След като свършите с писането на кода на CountPositive, компилирайте подпрограмата като изберете Compile VBAProject от менюто Debug. Разположете курсора в главната програма Vector и натиснете бутона със зелено триъгълниче. Ако излезе прозорецът
Macros, изберете Vector и натиснете Run. Ако трябва, въведете адреса и името на файла с входни данни, а ако не, приемете написаната в диалоговия прозорец Vector стойност по подразбиране като натиснете OK. Отидете на Sheet1 и разгледайте изписалия се под стойностите на елементите на вектор A резултат от броенето на положителните стойности в масива. Ако сте използвали стойностите предложени в началото на упражнението, би трябвало подзаглавието Брой положителни елементи във вектор A” да пише числото 4, което очевидно представлява коректния резултат от броенето на положителните елементи изписани по-горе на Sheet1. Намиране на максимален елемент във вектор
В третото подусловие на задачата, сред елементите на вектор A трябва да се намери и изведена най-големият по стойност. Най-добре е това подусловие също да се обособи като отделна подпрограма, още повече предвид факта, че на базата на текста му по-нататък самостоятелно ще трябва да напишете и друга част от програмата Vector, която намира минималния по стойност елемент на вектор B. В главната програма
Vector, позиционирайте курсора в края на извикването на подпрограмата CountPositive и натиснете Enter два пъти за да прескочите един ред. За следващото извикване може да използвате следния текст Намиране на максимален елемент във вектор
Call MaxArray(n, A, 7) В горния текст, за имена подпрограмата за намиране на максимум е използвано
MaxArray, а списъкът с фактически параметри включва размера на вектора, самия вектор, както и цяло число зареда на който да започне извеждането на резултата. При определянето на номера на реда е взето предвид, че пет реда вече са заети с извеждане на данни свързани с предишните две подусловия на задачата и че шестият ред е добре да остане празен за прегледност. По-късно, при самостоятелното решаване на деветото подусловие, можете да копирате извикването на MaxArray ида коригирате коментара, името, втория и третия параметър. Както вече беше обяснено в предишно упражнение, най-директният начин да се намери най-голямото от няколко числа е те да се сравнят помежду си, но броят на тези сравнения е голям дори за малко множество от стойности и нараства стремглаво с увеличаването наброя на данните измежду които се търси максимум, те. директното сравняване на стойностите на повече от три-четири числа е неприложимо на практика. Друг, практически по-използваем начин за намиране на най-голямото дори сред голямо множество от числа е чрез използването на една допълнителна променлива от същия тип както стойностите измежду които се търси екстремум - която често се нарича max, в която по времена търсене се съхранява временен максимум. В началото на този процес, още преди влизането в изчислителния цикъл, се приема, че първата измежду


8 стойностите е най-голяма и тя се присвоявана. След това max се сравнява подред с всяко следващо число от множеството. Ако някое от следващите числа се окаже по- голямо от max, предишната стойностна се изтрива и на нейно място се записва намерената по-голяма стойност. Така, по времена търсенето все съхранява временният максимум измежду разгледаните до този момент стойности. След като допълнителната променлива се сравни с всички стойности, в max остава записана най- голямата от тях. Подобен алгоритъм, включващ допълнителна променлива наречена примерно min, за чиято стойност подред се проверява дали е по-малка от всяко едно от сравняваните числа, се използва често при търсенето на минимум. Въпреки че в подусловие 3 на задачата не е записано изрично да се определи индексът на максималния елемент, добре би било и тази информация да се запише, примерно в целочислена променлива с името nmax – от номер на максималния елемент - непосредствено след намиране на стойността на максимума в изчислителния цикъл на подпрограмата MaxArray, както и накрая да се изведе наред със стойността на максимума. По принцип, при решаването на задачи по програмиране често е добре да се записва и извежда всичката информация получена при изчисленията, като например междинни резултати, индекси на важни елементи и т.н., защото не се знае дали тя в крайна сметка няма да се окаже полезна за целите на текущата задача или задруги, възникнали по-късно цели. Предвид характерното за този алгоритъм първоначално приемане, че най-голям по стойност е първият елемент от масива, началната стойностна трябва да е 1. Накрая на текста на MaxArray, името, индексът и стойността на намерения максимум трябва да се изведат под прегледно форматирано, описателно заглавие. За текст на MaxArray може да напишете следното
Sub MaxArray(n As Integer, A() As Single, r As Integer)
Dim max As Single, nmax As Integer, i As Integer max = A(1): nmax = 1
For i = 1 To n
If max < A(i) Then max = A(i) nmax = i
End If
Next i
With Cells(r, 1)
.Value = "Максимален елемент във вектор A"
.Font.Size = 14
.Font.Bold = True
End With
Cells(r + 1, 1).Value = "A(" & nmax & ")=" & max
End Sub


9 Като приключите с писането на кода на MaxArray, компилирайте подпрограмата като изберете Compile VBAProject от менюто Debug. Позиционирайте курсора в програмата
Vector и натиснете бутона със зелено триъгълниче. Ако излезе прозорецът Macros, изберете Vector и натиснете Run. Ако се налага, въведете адреса и името на файла с входни данни, а ако не, приемете написаната в диалоговия прозорец Vector стойност по подразбиране като натиснете OK. Отидете на Sheet1 и разгледайте изведения резултат от търсенето на най-големия по стойност елемент във вектор A. Ако сте използвали стойностите предложени в началото на упражнението, подзаглавието Максимален елемент във вектор A” трябва да пише A(7)=1.7, което означава, че измежду елементите на вектор A най-голям е седмият подред, чиято стойност е равна на 1.7. Разгледайте стойностите на елементите на вектор A изписани най-горе на Sheet1, за да се убедите, че полученият резултат е коректен. Фигура 2 Извеждане на Sheet1 на максимума във вектор A с програмата Vector Умножаване на елементите на вектор по константа
В четвъртото подусловие на задачата, от клавиатурата трябва да се въведе стойност за константа C, а после да се състави вектор B, чиито елементи представляват стойностите на всеки елемент от вектор A умножен по въведената стойност за C. Вектор B трябва да се изведена листа Sheet1 по същия начин като вектор A. Извеждането на вектор B се улеснява от факта, че по-рано създадохте подпрограмата OutArray, която сега трябва само да се извика след формирането на вектор B. Този факт онагледява доказаното на практика твърдение, че използването на подпрограми намалява общото количество код който програмистите трябва да пишат. Ако не бяхте обособили OutArray като отделен програмен модул, при извеждането на вектор B вместо единствения програмен ред с извикването на OutArray щеше да трябва да се напишат девет реда инструкции. В главната програма, оставете един празен ред след текста с извикването на последната подпрограма MaxArray и след това напишете Въвеждане на константа и умножаване на вектор по нея
Call MultiplyConstant(n, A, B, 10)


10 В горния текст за имена подпрограмата е използвано MultiplyConstant – умножава по константа, а списъкът от фактическите параметри се състои от размера на A, самия вектор A, вектор B, чийто стойности трябва да се получат от тези на елементите на A умножени по въведена от потребителя на програмата константа, и накрая реда на който да започне извеждането на вектор B, който е през един след запълнените дотук осем реда на Sheet1. За да се осигури задължителното съответствие между броя, реда и типа на данните участващи в списъка с формалните параметри и в този с фактическите, който вече беше даден при извикването на MultiplyConstant в главната програма Vector, в заглавния редна подпрограмата на трето място в скобите след името ѝ трябва да има масив от тип Single. В тялото на подпрограмата, освен управляващата променлива за цикъла For-Next в който ще се формира вектор B, трябва да се декларира и променлива в която да се запише въведена от клавиатурата стойност за константата C. В условието на задачата не е даден типът на константата, така че в общия случай може да се приеме, че е реална. Освен това не трябва да се забравя, че в главната програма Vector масивът
B беше деклариран като динамичен, те. все още не е определен размерът му. За да може в него да се записват стойностите на произведенията на всеки от елементите на A и константата C, вектор B трябва да се пре-декларира преди влизането в изчислителния цикъл по формирането му. Тъй като всеки от елементите на B се получавана базата на съответния елемент наброят на елементите на двата вектора е еднакъв и за размерна при пре-декларирането му ще се използва променливата n. С тези уточнения, за текст на подпрограмата MultiplyConstant може да напишете
Sub MultiplyConstant(n As Integer, A() As Single, _
B() As Single, r As Integer)
Dim C As Single, i As Integer
C = Въведете стойност за константа C:" & _ vbCrLf & "C=")
ReDim B(n)
For i = 1 To n
B(i) = A(i) * C
Next i Извежда векторна, "Вектор B")
End Sub След като напишете кода на MultiplyConstant, компилирайте подпрограмата с Compile
VBAProject от менюто Debug. Кликнете в програмата Vector и натиснете бутона със зелено триъгълниче. Ако излезе Macros, изберете Vector и натиснете Run. Ако трябва, въведете адреси имена файла с входни данни, а ако не, приемете написаната в прозореца Vector стойност по подразбиране като натиснете OK. В диалоговия прозорец за въвеждане на стойност за константа C, въведете число, като например 2, и натиснете


11
OK. После отидете на Sheet1 и разгледайте елементите на вектор B изписани наред, за да проверите дали стойностите им представляват съответните елементи на вектор A умножени по въведената от клавиатурата стойност за константата C. Ако забележите, че има грешки във формирането на вектор B, в програмния редактор редактирайте текста на извикването или на самата подпрограма MultiplyConstant, а след това я тествайте отново. Сортиране на вектор в нарастващ ред
В петото подусловие на задачата, елементите на вектор A трябва да се сортират по стойност в нарастващ реди след това да се изведат на Sheet1. И при неговото решение ще спестите писането на текст за извеждането и форматирането на заглавие и на стойностите на елементите чрез извикване на вече написаната подпрограма OutArray. Ако под изведения на Sheet1 вектор B се пропусне един ред за прегледност, заглавието на следващата част от задачата би трябвало да се разположи наред. В главната програма Vector, кликнете след текста на извикването на MultiplyConstant, натиснете
Enter два пъти и след това напишете Сортиране на вектор по стойност в нарастващ ред
Call SortAscending(n, A, 13) В горния текст името на подпрограмата за сортиране в нарастващ ред е SortAscending, тъй като за сортиране в нарастващ редна английски се използва словосъчетанието Sort in Ascending Order. Понеже в последното подусловие за самостоятелна работа се иска вектор B да се сортира в намаляващ ред, запомнете, че намаляващ редна английски е
“Descending Order” и че с копиране и минимални промени алгоритъмът за сортиране в нарастващ ред може да се преобразува в такъв за сортиране в намаляващ ред. При сортиране в нарастващ или намаляващ редна едномерен масив, всеки елемент, започвайки от първия, се сравнява последователно със следващите по индекс елементи на масива. Ако при това сравняване се установи, че два сравнявани вдаден момент елемента не са подредени пожелания начин, техните места се разменят. Елементите на вектора се избират за сравнение с помощта на 2 включени един в друг цикли For-Next. Във външния цикъл се избира един елемент с индекс i, те. A(i) ако става дума примерно за вектор с име A. Във вътрешния цикъл For-Next, A(i) подред се сравнява с елементите на вектора имащи индекси по-големи от текущата стойностна. Индексите по-големи от i се указват чрез използване на управляващата променлива на вътрешния цикъл, която задължително трябва да има име различно от това на брояча на външния цикъл - който по традиция се казва i - и за чието име по традиция се използва следващата след i буква от английската азбука, те. j. Така, при всяко повторение на вътрешния цикъл, елементът A(i) се сравнява с елемента с индекс j - A(j). В алгоритъма за сортиране в нарастващ ред, който трябва да се използва в подусловие 5 на текущата задача, ако при сравнението се установи, че A(i) има стойност по-голяма от тази на A(j), тези два елемента трябва да разменят местата си във вектор A, защото за един сортиран в нарастващ ред масив, всеки елемент има стойност по-малка от тази на елементите с по-големи индекси. При размяната на местата на елементите които не са подредени правилно, стойността на единия от тях трябва временно да се запише в допълнителна променлива от типа на подреждания масив, която се казва например B.


12 Фигура 3 Последователност на действията присмяна на местата на два елемента от вектор A Горната фигура показва последователността от действия които трябва да се извършват ако при сравненията извършващи се в двата вложени цикъла For-Next включени в алгоритъма за сортиране в нарастващ ред се установи, че стойността на елемента A(1) е по-голяма от тази на елемента A(4): първо, на променливата B се присвоява стойността на A(1); второ, стойността на A(4) се присвоявана А трето, записаната временно в променливата B предишна стойностна) се присвоявана. След пълно изпълнение на вътрешния цикъл, елементите на вектора се делят надве групи по отношение на i – група от вече сортирани елементи, чиито индекси са по- малки от текущата стойностна, и група от все още несортирани елементи, чиито индекси са по-големи от текущата стойностна. След всичките повторения на външния цикъл остава само групата от сортирани елементите. всички стойности на елементите на вектора вече са подредени в нарастващ ред. Единствената важна разлика между алгоритмите за сортиране в нарастващи в намаляващ ред е посоката на сравнение при сортиране в намаляващ ред местата на елементите се разменят ако се установи, че елементът с по-малък индекс има стойност по-малка от тази на елемент с по-голям индекс. Във външния цикъл с брояч i, индексите на елементите може да се изменят от 1 до n-1, те. до предпоследния елемент на масива, защото с вътрешния цикъл се избират елементите с по-големи индекси, а при сортирането последното сравнение което трябва да се направи е между стойностите на предпоследния и на последния елемент. Във вътрешния цикъл с брояч j, индексите на елементите може да се изменят от i+1 до n, тъй като няма смисъл даден елемент с индекс i да се сравнява с елемент с индекс j по- малък от този на брояча i, понеже това сравнение вече сее извършило при предишно повторение на циклите. Например, няма смисъл стойността на третия елемент да се сравнява с тази на втория, тъй като при предишно повторение на циклите вторият елемент вече е бил сравнен с третия и стойностите им са били разменени, ако сее установило, чене са подредени в желания ред. При писане на кода на подпрограмата SortAscending, както и за самостоятелното решаване на подусловие 10, в което вектор B трябва да се сортира в намаляващ ред, не забравяйте да декларирате две различни управляващи променливи за двата вложени цикъла For-Next, както и допълнителната променлива за временното съхраняване на стойността на единия елемент при размяната на местата на два елемента които не са подредени както трябва. След сортирането, подредените по стойност в нарастващ, или в намаляващ, ред елементи трябва да се изведат на листа Sheet1. В настоящата задача, това лесно може да стане с извикване на вече създадената подпрограма OutArray, която трябва да получи номера на реда на който трябва да започне извеждането, както и


13 заглавие описващо подредбата на елементите на вектора. За номер на реда се използва третият аргумент предаден на подпрограмата SortAscending при извикването ѝ от главната програма Vector. Предвид обясненото дотук, за SortAscending напишете
Sub SortAscending(n As Integer, A() As Single, r As Integer)
Dim B As Single, i As Integer, j As Integer
For i = 1 To n - 1
For j = i + 1 To n
If (A(i) > A(j)) Then
B = A(i)
A(i) = A(j)
A(j) = B
End If
Next j
Next i Извежда сортирания векторна, "Вектор A сортиран в нарастващ ред)
End Sub След като завършите кода на SortAscending, компилирайте подпрограмата с командата
Compile VBAProject от менюто Debug. Позиционирайте курсора в главната програма
Vector и натиснете бутона със зелено триъгълниче. Ако излезе Macros, изберете Vector и натиснете Run. Ако трябва, въведете адреси имена файла с входни данни, а ако не, приемете написаната в прозореца Vector стойност по подразбиране като натиснете OK. В диалоговия прозорец за въвеждане на стойност за константата C, въведете число, като например 2, и натиснете OK. После отидете на Sheet1 и разгледайте стойностите на елементите на вектор A изписани наред, за да проверите дали стойностите им са подредени в нарастващ ред. Ако видите, че има грешки при сортирането, в програмния редактор поправете текста на извикването или на самата подпрограма SortAscending, а след това пак я компилирайте и тествайте. Имайте предвид, че текстът на подусловие
10, който трябва да напишете самостоятелно, по същество се различава от този за
SortAscending само по посоката на сравнението в If. Намиране на скаларно произведение
В шестото подусловие на задачата трябва да се намери скаларното произведение на масива A, който току-що беше сортиран по стойност в нарастващ реди вектор B. Ако под изведения наред на листа Sheet1 сортиран вектор A се пропусне един ред за прегледност, заглавието на следващата част от задачата би трябвало да се разположи наред номер 16. В главната програма Vector, кликнете след извикването на SortAscending, натиснете Enter два пъти, а след това извикайте подпрограма с примерното заглавие
ScalarProduct последния начин Намиране на скаларно произведение на два вектора
Call ScalarProduct(n, A, B, 16)


14 Вдадения по-горе текст, списъкът от фактически параметри се състои от размера на двата масива, векторите A и B - чието скаларно произведение трябва да се пресметне - и номера на реда на който да започне извеждането на резултата от изпълнението на подпрограмата ScalarProduct. В линейната алгебра, скаларното произведение на два числови вектора с еднакъв размер представлява сумата от произведенията на съответните елементи на векторите, като под съответни елементи се разбира тези които имат един и същи индекс във всеки от масивите. В резултат от изчисляването на скаларното произведение на два вектора се получава една стойност представляваща описаната сума. Често, скаларно произведение се означава със знака за точка между имената на двата вектора, както в началото на следната формула Фигура 4 Алгебрична формула за скаларното произведение на два вектора a и b В горната формула, n е размерът, или броят елементи, на двата едномерни масива a и b, който по определение трябва да е един и същ за двата вектора. Вижте следния пример за скаларното произведение на два вектора, всеки от които се състои от три цели числа Фигура 5 Числов пример за скаларното произведение на два вектора от потри елемента Поначало, добре е дадената по-горе алгебрична формула за скаларно произведение да се знае наизуст, защото немалко условия на задачи за контролно или за изпит изискват да се намери скаларното произведение примерно на едномерни масиви, или на два реда в матрица или нареди колона в квадратна матрица, а формулата най-често не се дава. Ако дадените по-горе общи разяснения за намирането на скаларно произведение на два вектора се приложат към решаването на шестото подусловие на текущата задача, не е трудно да се заключи, че изчисляването на скаларно произведение се свежда до намиране на сума от n наброй произведения, което явно ще стане в цикъл For-Next. Преди записана цикъла, трябва да се декларират брояч за него и една променлива от типа на елементите на векторите, в която да се запише резултатът от изчисляването на скаларното произведение. Като подготовка за изчислителния цикъл, на променливата за резултата трябва да се присвои характерната за намиране на сума начална стойност 0. Така, предвид изискването резултатът да се изведе (прегледно) на Sheet1, примерният текст нае следният
Sub ScalarProduct(n As Integer, A() As Single, _
B() As Single, r As Integer)
Dim sc_pr As Double, i As Integer sc_pr = 0
For i = 1 To n sc_pr = sc_pr + A(i) * B(i)
Next i


15
With Cells(r, 1)
.Value = "Скаларно произведение на вектори A и B"
.Font.Size = 14
.Font.Bold = True
End With
Cells(r + 1, 1).Value = sc_pr
Cells(r + 1, 1).NumberFormat = "0.00000"
End Sub В горния текст, променливата sc_pr, в която се съхранява резултатът от изчисляването на скаларното произведение на два вектора от тип Single, е декларирана като Double за по-голяма точност. Като завършите кода на подпрограмата ScalarProduct, компилирайте я с Compile VBAProject от менюто Debug. Кликнете в програмата Vector и натиснете бутона със зелено триъгълниче. Ако се появи диалоговият прозорец Macros, изберете
Vector и натиснете Run. Ако трябва, въведете адреси имена файла с входни данни, а иначе, приемете дадената в прозореца Vector стойност по подразбиране като натиснете
OK. В диалоговия прозорец за въвеждане на стойност за константата C, въведете число, като например 2, и натиснете OK. После отидете на Sheet1 и вижте изведената наред номер 17 стойност за скаларното произведение на A и B. Ако сте използвали дадените дотук в упражнението стойности за елементите на едномерния масиви за константата
C, скаларното произведение на сортирания в нарастващ ред вектори на вектор B би трябвало да е -1.48. Тази стойност е резултат от сумирането на произведенията отдадените по-горе на Sheet1 съответни елементи на A и B, а именно
A · B = (-1.60) × 2.20 + (-1.40) × (-2.40) + (-1.20) × 2.60 +
+ 1.10 × (-2.80) + (1.30) × 3.00 + 1.50 × (-3.20) + (1.70) × 3.40 =
= (-3.52) + 3.36 + (-3.12) + (-3.08) + 3.90 + (-4.80) + 5.78 = -1.48 Ако сте използвали други данни, пресметнете скаларното произведение на A и B на ръка или с калкулатори сравнете полученото число с резултата изписан на Sheet1 от работата на подпрограмата ScalarProduct. Ако има значителна разлика в получените стойности, намерете допуснатите в програмния текстили в изчисленията грешки и ги поправете. Ако трябва, компилирайте и тествайте програмата Vector с подпрограмата
ScalarProduct пак. Намиране на средно-аритметичната стойност за едномерен масив
В седмото, и последно за работата в клас, подусловие на текущата задача трябва да се намери средното-аритметично на стойностите на елементите на вектор B. Прегледното извеждане на резултата трябва да започне през един ред под изведената на листа Sheet1 единична стойност за скаларното произведение, тена ред 19. В главната програма
Vector, кликнете след извикването на подпрограмата ScalarProduct, натиснете Enter два пъти и след това извикайте нова подпрограма с примерното име AverageArray – от думата Average която на английски език значи средна стойност - последния начин Намиране на средно-аритметично
Call AverageArray(n, B, 19)


16 В списъка с фактически параметри при извикването на AverageArray, внимавайте да дадете на подпрограмата вектора чието средно-аритметично се търси в подусловие 7, те. вектор B. По принцип, пресмятането на средно-аритметично се свежда, първо, до изчисляването на сума от стойностите на елементите на даден вектор с помощта на цикъл For-Next и, второ, до еднократното разделяне на намерената сума наброя на сумираните елементи след излизането от цикъла. Тази формула също често се използвана контролни и на изпити по Програмиране, като се предполага, че студентите я знаят наизуст. За записването ѝ в програмата е необходимо да се декларират променлива за съхраняване на резултата от изчисленията и брояч за цикъла For-Next. Получената за средното-аритметично стойност трябва прегледно да се изведена. Текстът е
Sub AverageArray(n As Integer, A() As Single, r As Integer)
Dim Avg As Single, i As Integer
Avg = 0
For i = 1 To n
Avg = Avg + A(i)
Next i
Avg = Avg / n
With Cells(r, 1)
.Value = "Средно-аритметично на вектор B"
.Font.Size = 14
.Font.Bold = True
End With
Cells(r + 1, 1).Value = Avg
End Sub Забележете, че за разлика от втория параметър B в списъка с фактически параметри при извикването на подпрограмата AverageArray в главната програма, на второ място в списъка с формални параметри в заглавния редна фигурира вектор с името A. Както стана ясно в предишното упражнение, не е задължително да се осигури съответствие между имената на формалните и фактическите параметри. След като напишете текста на AverageArray, компилирайте с командата Compile
VBAProject от менюто Debug. Кликнете в програмата Vector и натиснете бутона със зелено триъгълниче. Ако се появи прозорецът Macros, изберете Vector и натиснете Run. Ако има нужда, въведете адреси имена файла с входни данни, а ако няма, приемете написаната в прозореца Vector стойност по подразбиране като натиснете бутона OK. В диалоговия прозорец за въвеждане на стойност за константата C, въведете число, като например 2, и натиснете OK. После отидете на Sheet1 и вижте изведената наред стойност за средното-аритметично на елементите във вектор B. Ако сте използвали предложените по-рано в упражнението данни, средното-аритметично би трябвало да е
0.4. Препоръчително е да проверите дали резултатът е верен, като изчислите средното- аритметично на елементите във векторна ръка или с калкулатор. Ако сте въвели


17 други данни, проверете получения за тях резултат. Ако има значима разлика, намерете и отстранете грешките които сте допуснали. Ако трябва, пак компилирайте и тествайте програмния текст. След извикването и изпълнението на подпрограмите за първите 7 подусловия на текущата задача със споменатите в течение на решаването им данни, на Sheet1 трябва да са изведени следните резултати от работата на програмата Vector: Фигура 6 Извеждане на Sheet1 на резултати от работата на програмата Vector Целият написан дотук текст на програмата Vector е следният
Option Explicit
Sub Vector()
Dim n As Integer, A() As Single, B() As Single Въвеждане на вектор
Call InputArray(n, A) Броене на положителни елементи
Call CountPositive(n, A, 4) Намиране на максимален елемент във вектор
Call MaxArray(n, A, 7) Въвеждане на константа и умножаване на вектор по нея
Call MultiplyConstant(n, A, B, 10) Сортиране на вектор по стойност в нарастващ ред
Call SortAscending(n, A, 13)


18 Намиране на скаларно произведение на два вектора
Call ScalarProduct(n, A, B, 16) Намиране на средно-аритметично
Call AverageArray(n, B, 19) Домашно Броене на отрицателни елементи във вектор 'Домашно Намиране на минимален елемент във вектор 'Домашно Сортиране на вектор по стойност в намаляващ ред
End Sub
Sub InputArray(n As Integer, A() As Single)
Dim i As Integer, FName As String
' Въвеждане на адреси имена файла с входни данни
FName = Адреси имена файл с входни данни, _
"Vector", "d:\vector.txt")
If Dir(FName) = "" Then
MsgBox (Файлът " & FName & " не е намерен !!!")
Stop
End If
Close #1
Open FName For Input As #1 Въвежда вектор
Input #1, n
ReDim A(n)
For i = 1 To n
Input #1, A(i)
Next i
Close #1
' Извежда векторна, "Вектор A")
End Sub


19
Sub OutArray(n As Integer, A() As Single, _ r As Integer, title As String)
Dim i As Integer
With Cells(r, 1)
.Value = title
.Font.Size = 14
.Font.Bold = True
End With
For i = 1 To n
Cells(r + 1, i).Value = A(i)
Cells(r + 1, i).NumberFormat = "0.00"
Next i
End Sub
Sub CountPositive(n As Integer, A() As Single, r As Integer)
Dim cnt_Pos As Integer, i As Integer cnt_Pos = 0
For i = 1 To n
If A(i) > 0 Then cnt_Pos = cnt_Pos + 1
End If
Next i
With Cells(r, 1)
.Value = "Брой положителни елементи във вектор A"
.Font.Size = 14
.Font.Bold = True
End With
Cells(r + 1, 1).Value = cnt_Pos
End Sub
Sub MaxArray(n As Integer, A() As Single, r As Integer)
Dim max As Single, nmax As Integer, i As Integer max = A(1): nmax = 1
For i = 1 To n


20
If max < A(i) Then max = A(i) nmax = i
End If
Next i
With Cells(r, 1)
.Value = "Максимален елемент във вектор A"
.Font.Size = 14
.Font.Bold = True
End With
Cells(r + 1, 1).Value = "A(" & nmax & ")=" & max
End Sub
Sub MultiplyConstant(n As Integer, A() As Single, _
B() As Single, r As Integer)
Dim C As Single, i As Integer
C = InputBox("Въведете стойност за константа C:" & _ vbCrLf & "C=")
ReDim B(n)
For i = 1 To n
B(i) = A(i) * C
Next i
'Извежда вектор B на Sheet1
Call OutArray(n, B, r, "Вектор B")
End Sub
Sub SortAscending(n As Integer, A() As Single, r As Integer)
Dim B As Single, i As Integer, j As Integer
For i = 1 To n - 1
For j = i + 1 To n
If (A(i) > A(j)) Then
B = A(i)
A(i) = A(j)
A(j) = B
End If


21
Next j
Next i Извежда сортирания векторна, "Вектор A сортиран в нарастващ ред)
End Sub
Sub ScalarProduct(n As Integer, A() As Single, _
B() As Single, r As Integer)
Dim sc_pr As Double, i As Integer sc_pr = 0
For i = 1 To n sc_pr = sc_pr + A(i) * B(i)
Next i
With Cells(r, 1)
.Value = "Скаларно произведение на вектори A и B"
.Font.Size = 14
.Font.Bold = True
End With
Cells(r + 1, 1).Value = sc_pr
Cells(r + 1, 1).NumberFormat = "0.00000"
End Sub
Sub AverageArray(n As Integer, A() As Single, r As Integer)
Dim Avg As Single, i As Integer
Avg = 0
For i = 1 To n
Avg = Avg + A(i)
Next i
Avg = Avg / n
With Cells(r, 1)
.Value = "Средно-аритметично на вектор B"
.Font.Size = 14
.Font.Bold = True
End With


22
Cells(r + 1, 1).Value = Avg
End Sub Самостоятелно решаване на подусловия на задача с вектори
Предвид големия обемна работата свършена дотук в упражнението, както и факта, че вероятно в бъдеще ще трябва да преговаряте този материал, най-добре е да запишете работната книга Book1 в която работихте досега на магнитен носител до който имате редовен достъп, примерно под името Vector. Ако използвате сравнително нова версия нане забравяйте при записването на файла от списъка вдясно от Save as type: да изберете Excel Macro-Enabled Workbook за тип на работната книга, за да сте сигурни, че текстът на програмата ще се запише. В края на програмата в работната книга Vector, в немного по-късен момент - докато все още си спомняте подробностите от научения в текущото упражнение материал - се изисква да добавите работещ програмен текст по подусловия 8, 9 и 10, които трябва да решите самостоятелно. За намирането наброя отрицателни елементи във вектор B, може да копирате текста на подпрограмата CountPositive, да смените името ѝ и това на променливата за резултата с цел да не подведете някой неподготвен читател, но от най-голяма важност е да редактирате условието след If в изчислителния цикъл на подпрограмата, така че то да отразява критерия за броене даден в подусловие 8, те. да се броят отрицателните елементи. Резултатът трябва да се изпише под прегледно форматирано, описателно заглавие. При извикването на подпрограмата за броене на отрицателните елементи, внимателно преценете кой от двата използвани досега вектора трябва да ѝ се предаде и на кой ред да започне извеждането на резултата ѝ. За намирането на най-малкия по стойност елемент във вектор B, може да копирате текста на подпрограмата MaxArray ида смените нейното име, а вътре в нея - и тези на променливите за стойността и индекса на минималния елемент. Най-важно, обаче, остава да коригирате посоката на сравнение след If в изчислителния цикъл. В извикването на подпрограмата за намиране на най- малък елемент трябва да фигурира споменатият в подусловие 9 вектори подходящ номер наред за извеждане на резултата. Най-накрая, за сортирането на вектор B по стойност в намаляващ ред, може да започнете с текста на SortAscending, да смените името ѝ, например на SortDescending, както и текста на заглавието което се предава като аргумент при извикването на подпрограмата OutArray. В текста е най-важно да смените посоката на сравнение след If във вътрешния от двата вложени изчислителни цикъла. В извикването ѝ в програмата Vector, внимавайте кой вектор трябва да се сортира и на кой ред да започне изписването на сортирания в намаляващ ред масив. Ако нещо се обърка в написания от Вас текст на програмата Vector или с файла в който е записан този код, в папката VBAps5 под името Vector-Prog може да намерите файл сдадения по-горе текст на програмата Vector, към който да добавите решенията на подусловия 8, 9 и 10. Не забравяйте първо да създадете ида запишете използваем файл с входните за програмата данни, а после в началото на подпрограмата InputArray да въведете валидни за компютъра на който работите адреси имена този файл.


Сподели с приятели:




©obuch.info 2024
отнасят до администрацията

    Начална страница