1 Algoritmes en computerprogramma s
|
|
|
- Maria Timmermans
- 9 jaren geleden
- Aantal bezoeken:
Transcriptie
1 1 Algoritmes en computerprogramma s 1.1 Basiselementen van een computer Een computer is opgebouwd uit een heleboel verschillende onderdelen. Een schematisch diagram wordt getoond in de volgende figuur. secundair geheugen CD-ROM hard disk USB-stick tape computer box CPU RAM in/uitvoer apparatuur scanner toetsenbord beeldscherm muis printer Er zijn drie belangrijke elementen: het secundair geheugen voor grote hoeveelheden gegevens op te slaan; de computer box samengesteld uit de Central Processing Unit (CPU) en werkgeheugen of Random Access Memory (RAM); de in/uitvoer (I/O) apparatuur voor de interactie tussen de gebruiker en de computer. Deze fysische onderdelen van de machine noemt men de hardware. Software zijn verzamelingen instructies die er voor zorgen dat de hardware operaties en berekeningen uitvoert. Software wordt geschreven in een programmeertaal. Zo n programmeertaal moet een aantal elementen bevatten om de processor berekeningen te laten uitvoeren; om informatie efficiënt beschikbaar te hebben in het werkgeheugen; om de communicatie te verzekeren met de gebruiker via toetsenbord, muis, beeldscherm,...; om grote hoeveelheden gegevens te kunnen lezen van secundaire geheugens en om resultaten te kunnen schrijven naar die secundaire geheugens voor latere raadpleging. 1.2 Algoritmes Computers worden gebruikt om problemen op te lossen. Om tot een oplossing te komen, moeten berekeningen uitgevoerd worden: de som van een aantal getallen; een tabel met x-waarden en bijhorende functiewaarden; een nulpunt van een functie; de bepaalde integraal van een functie tussen twee grenzen; de oplossing van een stelsel lineaire vergelijkingen;... 1
2 Sommige van deze berekeningen zijn heel eenvoudig, voor andere bestaat de berekening uit een heleboel stappen. Een berekening kan beschreven worden in de vorm van een algoritme. Een algoritme is een duidelijke en preciese procedure (een opeenvolging van goed-gedefinieerde stappen) om een gegeven probleem op te lossen. Een voorbeeld is het algoritme van Gauss voor het oplossen van een stelsel lineaire vergelijkingen. Voor heel veel problemen bestaan (nog) geen algoritmes die het probleem exact oplossen. In die gevallen wordt dikwijls een beroep gedaan op een procedure die een benaderende oplossing genereert, bijvoorbeeld de trapeziumregel voor het berekenen van een bepaalde integraal. Niettegenstaande een algoritme een precieze beschrijving van de oplossingsprocedure is, is dit meestal niet door een computer interpreteerbaar. Het algoritme moet omgezet worden in een programma. Een programma is geschreven in een programmeertaal. Een computerprogramma is een lijst van instructies welke door de processor interpreteerbaar en uitvoerbaar zijn. Een programma kan ook gezien worden als een verzameling van data en routines om deze data te verwerken. Deze routines (procedures of functies) worden neergeschreven met behulp van instructies. De processor voert deze instructies sequentiëel (één na één) uit. Een computerprogramma moet dus (in het algemeen) zoals een tekst gelezen worden: lijn per lijn van boven naar onder. Elke lijn bevat een aantal instructies voor de processor. Een programmeertaal bevat een aantal speciale keywords om aan te geven dat een aantal instructies in herhaling moeten uitgevoerd worden of dat een beslissing moet gemaakt worden omtrent welke set instructies moeten uitgevoerd worden. Naast een sequentiële uitvoering van een programma is er dus de mogelijkheid voor een lus : de mogelijkheid om een verzameling instructies een aantal maal na elkaar uit te voeren; keuze : de mogelijkheid om te beslissen welke verzameling instructies uitgevoerd worden. Begin instructie 1 instructie 2 instructie 3. instructie i 1 instructie i. instructie n Einde sequentie Begin instructie 1 while (voorwaarde) instructie 2 instructie 3 instructie 4 instructie 5. instructie n Einde herhaling Begin instructie 1 if (voorwaarde) instructie 2 else instructie 3 instructie 4. instructie n Einde keuze Deze drie elementen, sequentie, herhaling (iteratie) en keuze, bepalen de controle stroom doorheen het programma. 1.3 Som van twee getallen Een eerste poging De som van twee getallen maken is vrij eenvoudig: In de CPU is namelijk een elementaire machine-instructie aanwezig om een optelling uit te voeren. Om het resultaat van deze bewerking te zien is een gereedschap nodig dat deze bewerking leest, interpreteert en uitvoert en dan het resultaat toont. 2
3 Python kan hiervoor gebruikt worden, door deze in interactieve mode te starten. Afhankelijk van de gebruikte omgeving kan dit gebeuren door aan de shell prompt python in te tikken of door op het gepaste icoontje op de desktop te klikken: Python ( r265 :79063, Jul , 11:46:13) [GCC [ gcc 4 5 branch revision ]] on linux2 Type help, copyright, c r e d i ts or l i c e n s e for more information. >>> De chevron, >>> is de prompt en geeft aan dat de Python interpreter klaar is om invoer in te lezen. >>> >>> Nadat , gevolgd door een enter (return) ingetikt is, berekent de Python interpreter het resultaat en toont dit. Op deze manier kan de Python interpreter als rekenmachine gebruikt worden. Deze interactieve mode laat ook toe om korte stukken programma code in te tikken en uit te voeren: >>> a = >>> b = 9852 >>> a+b >>> a b 3553 >>> In de berekening worden geen concrete gehele getallen vermeld, maar variabelen. Zo n variabele is een symbolische naam van een (getal)waarde of meer algemeen van een object. Deze waarde wordt in een geheugenplaats in het centraal geheugen van de computer geplaatst. Deze naam aan een waarde toewijzen gebeurt met een toekenning: a = Deze waarde (23405) heeft een type. Het type geeft aan hoe groot de geheugenplaats moet zijn, en dus hoeveel bytes voor de desbetreffende waarde moet voorzien worden. In dit voorbeeld wordt een geheel getal gebruikt, men spreekt van het type int. Het type van een waarde bepaalt ook welke operaties (bewerkingen) toegelaten zijn. Op waarden van het type int kunnen de verschillende rekenkundige bewerkingen uitgevoerd worden: +, -, *, /, % en **. Voor de deling zijn twee operaties voorzien, namelijk voor de berekening van het quotiënt en de rest: 34 / 6 --> 5 34 % 6 --> 4 Naast waarden van type int zijn ook float waarden beschikbaar waarmee echte delingen kunnen gebeuren: 34.0 / > % > Een script versie Python kan ook in script versie gebruikt worden. Het programma wordt ingetikt in een bestand. De suffix van de naam van dit bestand is.py. 3
4 1 # som1.py: eerste poging De eerste lijn geeft uitleg over het programma dat volgt. Dit is voor de (menselijke) lezer van het programma bestemd en wordt commentaar genoemd. Alles wat zich achter een # bevindt, is commentaar en heeft geen betekenis voor de computer. Daarna volgen de instructies die door de computer moeten uitgevoerd worden. In plaats van instructie wordt in het computer-jargon statement gebruikt. In dit geval gaat het over een optelling. Het einde van een statement wordt aangegeven door het einde van de lijn. Bij het starten van python wordt dit bestand als argument meegegeven: % python som1.py % Er is echter geen resultaat te zien, omdat er geen visueel effect is van een rekenkundige expressie in de script mode van de Python interpreter. Als programma (of script) is bovenstaande vrij nutteloos. De computer heeft wel de som van twee getallen berekend, maar het resultaat zou moeten zichtbaar gemaakt worden. Daarnaast kan het programma maar de som van twee specifieke getallen berekenen. Wanneer de som van twee andere getallen moet berekend worden, moet het programma aangepast worden. Om een volwaardig programma te maken, zijn variabelen nodig en communicatie met de gebruiker via toetsenbord en beeldscherm. # som2.py: een meer zinvolle poging 2 def main ( ) : invoer = raw input ( Geef getal 1: ) 4 a = int ( invoer ) invoer = raw input ( Geef getal 2: ) 6 b = int ( invoer ) som = a + b 8 print som # startoproep 10 main () Met behulp van def wordt een functie gedefinieerd. Afspraak is dat elk python programma minstens de functie main bevat. De twee haakjes (()) geven aan dat het vorige woord de naam van een functie is. Na : volgt de definitie van de functie: een aantal statements die in deze functie moeten uitgevoerd worden. Deze eerste lijn wordt de hoofding van een functie genoemd. Het blok met statements is het lichaam van de functie; deze statements zijn geïndenteerd. De uitvoering van deze functie wordt gestart door de laatste lijn van het programma, dit is de oproep van de functie. In de berekening worden geen concrete gehele getallen vermeld, maar variabelen. Een variabele is een symbolische naam van een (getal)waarde in het werkgeheugen. De combinatie van zo n geheugenplaats met een waarde wordt object genoemd. Het statement waarin de berekening gebeurt (som van twee getallen) werkt met variabelen: neem de inhoud van variabele a (waarde van het object) ; tel hierbij de inhoud van variabele b (waarde van het object) op; geef het object met resultaatwaarde de naam som (variabele). Het = teken is het symbool voor de operatie toekenning. Langs de rechterkant van dit symbool worden de waarden van objecten (in dit geval numerieke waarden) gebruikt; langs de linkerkant 4
5 staat een naam (variabele) die vanaf dan het object met daarin de waarde van het resultaat van de bewerking aanduidt. Wanneer een variabele langs de rechterkant van een = gebruikt wordt, moet deze een waarde hebben. Dit kan bijvoorbeeld gebeuren door deze in te lezen van het toetsenbord. De communicatie met de gebruiker is een vrij moeilijke taak. Maar hiervoor zijn standaard elementen voorzien, raw_input voor invoer van het toetsenbord en print voor uitvoer naar het beeldscherm. Met behulp van raw_input kan wat ingetikt wordt op een toetsenbord, ingelezen worden in een waarde. Wanneer deze functie opgeroepen wordt, wacht de Python interpreter totdat de gebruiker iets intikt en afsluit met enter (return). De ingetikte tekens worden als object teruggeven uit de functie. Aan dit object wordt een naam toegewezen door middel van de = operator. Deze variabele bevat nu een opeenvolging van tekens die door de gebruiker op het toetsenbord ingetikt zijn (zonder de enter). Zo n opeenvolging van tekens is van type string. Probleem hiermee is dat op strings geen rekenkundige bewerkingen kunnen gebruikt worden. Met behulp van de functie int kan de ingegeven string omgezet worden in een geheel getal. Aan dit resulterend object wordt een naam toegewezen door middel van de = operator. Om een gebruiksvriendelijk programma te hebben, moet natuurlijk aan de gebruiker aangegeven worden wat er door het programma verwacht wordt dat er ingetikt wordt. Deze prompt kan als argument bij input meegegeven worden. Met behulp van hetprint statement wordt de waarde van de variabele die bij print vermeld wordt, op het scherm getoond. In plaats van alleen het resultaat te tonen, kunnen ook de twee ingegeven getallen getoond worden, samen met de uitgevoerde bewerking: print a, +, b, >, som Het print statement heeft nu verschillende argumenten, gescheiden dooor komma s. Van de argumenten a, b en som wordt de waarde genomen en deze wordt getoond op het scherm. De argumenten die beginnen en eindigen met een quote ( ) zijn strings: deze worden zonder meer op het scherm getoond. Het resultaat wordt nu: > Merk op dat print zelf zorgt voor gepaste spaties tussen de verschillende elementen. Het print statement kan vervangen worden door een aantal print statements: print a, print +, b, print >, som De komma op het einde van eenprint geeft aan dat nog niet naar een volgende lijn mag overgegaan worden. Omdat in de strings extra spaties opgenomen zijn, worden in het resultaat ook deze spaties getoond: > Omzetting mijl naar kilometer Het algoritme om een gegeven aantal mijl om te zetten in een aantal kilometers is vrij eenvoudig: vermenigvuldig het aantal mijl met de factor Opgave. Schrijf een programma dat 10 mijl omzet naar km. 1 # mijl1km.py: omzetting van 10 mijl naar km def main ( ) : 3 mijl = 10.0 km = mijl print mijl, mijl i s, km, kilometer # startoproep 5
6 7 main () In dit programma worden constanten 10.0 en gebruikt. Deze zijn van type float (reële getallen). Op waarden van het type float kunnen de verschillende rekenkundige bewerkingen uitgevoerd worden: +, -, *, / en ** (en ook de minder zinvolle %). Opgave. Schrijf een programma dat een afstand in mijl inleest en het overeenkomstig aantal kilometer afdrukt. 1 # mijl2km.py: omzetting van mijl naar km def main ( ) : 3 invoer = raw input ( Geef het aantal mijl : ) mijl = float ( invoer ) 5 km = mijl print mijl, mijl i s, km, kilometer 7 # startoproep main () De afstand die als string ingelezen wordt, moet omgezet worden naar een reëel getal. Dit kan door de functie float. 1.5 Berekening van de grootste gemene deler Opgave. Lees twee gehele getallen en bereken de grootste gemene deler (ggd) van deze twee getallen. In dit geval (ggd), kan beroep gedaan worden op het algoritme van Euclides: 1. Noem de twee getallen x en y met x < y. 2. Bereken de rest r bij deling van y door x. 3. Vervang y door x, en x door r. 4. Herhaal stap 2 en 3 totdat r nul is. 5. De grootste gemene deler is gelijk aan y. Voorbeeld: ggd van en de rest van de deling 34017/16966 is gelijk aan 85 de rest van de deling 16966/85 is gelijk aan 51 de rest van de deling 85/51 is gelijk aan 34 de rest van de deling 51/34 is gelijk aan 17 de rest van de deling 34/17 is gelijk aan 0 de grootste gemene deler van en is gelijk aan 17. Om dit algoritme door een computer te laten uitvoeren, moet dit omgezet worden naar een computerprogramma. # ggd. py: bereken grootste gemene deler van twee getallen 2 def main ( ) : invoer = raw input ( Geef eerste getal : ) 4 a = int ( invoer ) invoer = raw input ( Geef tweede getal : ) 6 b = int ( invoer ) if a > b : 8 x = b y = a 6
7 10 else : x = a 12 y = b while x!= 0 : 14 r = y % x y = x 16 x = r print ggd(, a,,, b, ) i s, y 18 # startoproep main () Naast statements met toekenningen en in/uitvoer functies, bevat dit programma twee nieuwe statements: een if en een while statement. Dit zijn voorbeelden van controle-statements om de sequentiële uitvoering van het programma om te kunnen buigen. Het if statement (keuze) wordt gebruikt om de getalwaarden van de twee ingelezen getallen aan de variabelenxen y toe te wijzen zodat de waarde van object met naam x kleiner is dan de waarde van object met naam y (x < y). Het while statement (herhaling) is een mogelijke vertaling van de Herhaal stap in het algoritme van Euclides. Deze twee statements zijn compound of blok statements omdat onderdelen ervan zelf statements zijn. De vorm waarin het programma ingetikt wordt, is bij Python vastgelegd: de statements van het hoofdblok moeten in de eerste kolom beginnen. Net zoals bij def moeten statements die horen bij een if en een while geïndenteerd worden: hiermee wordt het begin en het einde van een blok aangegeven. Dit bevordert ook de leesbaarheid van het gehele prgramma. In de beschrijving van het algoritme gebeurt de test of de rest gelijk is aan 0 op het einde. Deze test gebeurt in het programma in het begin. In het programma is deze aanpassing nodig voor een goede afloop van het programma wanneer één van de ingelezen getallen gelijk is aan nul (ggd(0,1) = 1!). 1.6 Python omgeving In het vorige is aangegeven dat Python zowel in interactieve mode als in script mode kan gebruikt worden. In de volgende hoofdstukken zullen de verschillende concepten meestal geïllustreerd worden met behulp van Python scripts. Sporadisch zal de interactieve mode gebruikt worden om bepaalde effecten te illustreren. Dit wordt aangegeven door de transcriptie te plaatsen in een kader met afgeronde hoeken. In interactieve mode kunnen volledige scripts uitgevoerd worden door middel van de execfile functie, met de naam van het script als argument. >>> e x e c f i l e ( mijl1km. py ) 10.0 mijl is kilometer 1.7 Begrippen Een algoritme. Interactieve mode van een interpreter Een programma: interpretatie en uitvoering. Objecten: waarden (met type) en symbolische namen (variabelen). Rekenkundige en logische expressies. De main functie. Statements: toekenning, invoerfunctie (raw_input), uitvoerstatement (print). 7
8 2 Numerieke data en expressies 2.1 Constanten In het werkgeheugen kunnen volgende soorten data voorgesteld worden. Deze data moet door de CPU kunnen verwerkt worden. Integers : een exacte voorstelling van gehele getallen over een beperkt bereik (eventuele overflow/underflow problemen). Floating point numbers : een niet-exacte voorstelling van reële getallen omdat een eindige binaire string niet om het even welk reëel getal kan voorstellen; het bereik is veel groter dan bij integers. Strings : tekens tussen quotes, bijv. appel, zie een volgend hoofdstuk. Voorbeelden: gehele constanten reële constanten 123 (decimaal) (octaal).5 0x123 (hexidecimaal) 5. 5e4 Daarnaast zijn er ook de logische constanten True (voorgesteld door een niet-nul getal) en False (voorgesteld door een nul) beschikbaar. 2.2 Variabelen Een variabele is een symbolische naam voor een object of een geheugenplaats. Zo n naam kan ook worden aangeduid met de term identifier. Het is een rij letters en/of cijfers; tevens mag de underscore (_) in de naam voorkomen. Een naam mag niet beginnen met een cijfer. Hoofdletters en kleine letters worden als verschillend beschouwd. Er is geen beperking op de lengte, maar in sommige implementaties zijn bijvoorbeeld alleen de eerste acht tekens significant; de overige worden dan eenvoudig genegeerd (dit_is_een_variabele_voor_de_som). Een naam wordt door de programmeur gekozen. In de mate van het mogelijke moet de naam betekenisvol zijn: de naam moet iets vertellen over de functie van het object in het programma. Een variabele wordt niet gedeclareerd als zijnde van een bepaald type. Maar op het moment dat aan een object een naam toegekend wordt, is het type van de variabele vastgelegd op basis van het type van het object. Dit type bepaalt hoeveel bytes in het werkgeheugen nodig zijn voor zo n object. Het geeft ook aan welke operatoren toegelaten zijn op het object. int 8 bytes gehele getallen float 8 bytes reële getallen In volgende hoofdstukken zullen nog andere types aan bod komen. # varid. py: variabelen: geheel getal en reeel getal 2 def main ( ) : i = 2 4 j = 5 / 3 f f = 5.0 / 3 6 print i =, i print j =, j 8 print f f =, f f # startoproep 10 main () 8
9 De output van dit programma is: i = 2 j = 1 ff = Merk op dat de deling van twee gehele getallen (variabele j) het geheeltallig quotiënt oplevert. 2.3 Expressies De algemene vorm van een eenvoudige expressie is: operand_1 operator operand_2 zoals bijvoorbeeld a + b Rekenkundige expressies Rekenkundige operatoren: + optelling - aftrekking * vermenigvuldiging / deling het quotiënt % modulus de rest bij geheeltallige deling ** machtsverheffing De operatoren *, / en % hebben een hogere prioriteit dan + en -. Machtsverheffing heeft nog een hogere prioriteit. Naast deze binaire operatoren kan ook het unaire plusteken (+) en het unaire minteken (-) vermeld worden, met een prioriteit net lager dan **. >>> >>> Wanneer beide operands van hetzelfde type zijn, is het resultaat van de expressie ook van dat type: >>> 1 / 2 0 >>> 1.0 / >>> +5 % 3 2 Wanneer één operand int is en de ander float, wordt de int operand omgezet naar een float en dan wordt de operator uitgevoerd. Het resultaat van de expressie is float: >>> 1 / >>> 1.0 /
10 2.3.2 Logische expressies Een logische expressie heeft twee mogelijke uitkomsten: waar of True : alle niet nul-waarden; onwaar of False : een nul-waarde In een eenvoudige logische expressie worden de waarden van twee objecten (of expressies) met elkaar vergeleken, met behulp van relationele operatoren. Om eenvoudige logische expressies te combineren, gebruikt men logische operatoren: relationeel logisch < kleiner dan not logische niet (unair) <= kleiner dan of gelijk aan and logische en > groter dan or logische of >= groter dan of gelijk aan == gelijk aan!= verschillend van Voorbeelden: >>> x = 10.0 >>> x <= 40.0 # heeft x een waarde kleiner dan of gelijk aan 40.0 True >>> 2.0 < x and x < 7.5 # is waarde van x gelegen tussen 2.0 en 7.5 False In tegenstelling tot vele andere programmeertalen kunnen relationele operatoren geketend worden: de expressie 2.0 < x < 7.5 heeft dus dezelfde semantische betekenis als de meer complexe 2.0 < x and x < 7.5. Merk ook het verschil op tussen = (toekenning) en == (test op gelijkheid). x = 5 x == 5 # toekenning: geeft aan bbject met waarde 5 een naam # test: alleen waar als het object met naam x # als inhoud de waarde 5 heeft Combinatie van eenvoudige logische expressies: exp1 and exp2 is waar wanneer zowel exp1 als exp2 waar is; exp1 or exp2 is waar wanneer één van beide (exp1 en/of exp2) waar is; not exp1 is waar wanneer exp1 niet waar is. Dit wordt meestal weergegeven in waarheidstabellen: e1 and e e1 or e not e1 Kortsluitingsprincipe: bij een logische operator wordt de tweede operand niet geëvalueerd tenzij dit nodig is. Dus, een operand na and of or wordt niet meer berekend als de operand ervoor al uitsluitsel over het resultaat geeft. (De waarde van de tweede operand is van geen belang.) Toepassing: n!=0 and t/n>1 n==0 or t/n>1 0 and... # heeft de waarde 0 (false) 1 or... # heeft de waarde 1 (true) # wanneer n gelijk is aan nul wordt t/n niet berekend # wanneer n gelijk is aan nul wordt t/n niet berekend In tegenstelling tot sommige andere talen, geven deze expressies geen Run time error. 10
11 2.3.3 Toekenningsstatements Het resultaat van een expressie wordt meestal toegekend aan een variabele. Hiervoor wordt de toekenningsteken (=) gebruikt. x = y + z Eerst wordt de waarde van het rechterdeel, de expressie y+z, berekend: hiervoor worden de waarden van de objecten met namen y en z gebruikt. Het resulterende object wordt dan een naam toegewezen, aangegeven door het linkerdeel, de variabele x. Langs de linkerkant van het toekenningsteken moet steeds een naam staan: namelijk de naam die vanaf dan kan gebruikt worden om het object aan te spreken. (Langs links kan dus geen constante, bijvoorbeeld 6, staan want een constante kan niet als naam gebruikt worden van een object.) Langs de rechterkant van het = teken worden de waarden van de verschillende objecten gebruikt. Met deze waarden wordt een resultaat berekend. Ook aan het resultaat van een logische expressie kan een naam toegekend worden: 1 # logex. py: logische expressies def main ( ) : 3 invoer = raw input ( Geef eerste getal : ) a = int ( invoer ) 5 invoer = raw input ( Geef tweede getal : ) b = int ( invoer ) 7 r = a<=0 or b>=10 print r (, a,,, b, ) i s, r 9 r = a>0 and b<10 print r (, a,,, b, ) i s, r 11 # startoproep main () Het is mogelijk om de waarde van het rechterdeel aan meerdere variabelen toe te wijzen: a = x = y + z De waarde van y+z wordt berekend en hieraan wordt zowel variabele x als variabele a toegewezen. Langs de linkerkant van het = kunnen ook meerdere variabelen gescheiden door kommas s staan: a, b = 3, 9 Langs de rechterkant moeten dan evenveel expressies (in het voorbeeld constanten) gescheiden door komma s staan. De toekenningen gebeuren opeenvolgend: a wordt de naam van het object met waarde 3 en b de naam van het object met waarde 9. Wanneer het resultaat van een operatie op een variabele terug toegewezen wordt aan deze variabele, kan dit korter geschreven worden. Bij deze operatoren wordt een rekenbewerking gecombineerd met een toekenning. Ze worden ook toekenningsoperatoren genoemd. i += 4 i = i + 4 z -= x z = z - x k *= j k = k * j d /= 3 d = d / 3 z %= y z = z % y z **= y z = z ** y Bijvoorbeeld, bij i += 4 wordt eerst de waarde van het object met naam i bepaald. Bij deze waarde wordt 4 bijgeteld; het resulterende object (met de nieuw berekende waarde) krijgt terug de naam i toegewezen. Net zoals bij het gewone toekenningsteken moet langs de linkerkant steeds een variabele staan Prioriteit en associativiteit Wanneer verschillende operatoren in één expressie gebruikt worden, gelden prioriteitsregels om te bepalen welke operator eerst moet uitgevoerd worden. Deze regels kunnen natuurlijk opgeheven worden door gebruik te maken van haakjes ( () ). 11
12 Overzicht van de reeds geziene operatoren gerangschikt van hoge naar lage prioriteit: ** rechts - + rechts * / % links + - links ==!= < <= > >= links not rechts and links or links Het unaire min-teken (voor negatieve getallen) is terug te vinden op de tweede lijn en heeft dus een hogere prioriteit dan de andere rekenkundige binaire operatoren, met uitzondering van de machtsverheffing. Wanneer twee operatoren van dezelfde prioriteit in een expressie voorkomen, dan wordt gekeken naar de associativiteit. De meeste operatoren associëren van links naar rechts: a+b+c wordt geïnterpreteerd als (a+b)+c. Machtsverheffing en unaire operatoren worden uitgevoerd van rechts naar links: bijv. a = --c wordt geïnterpreteerd als a = -(-c). >>> >>> 8/2/2 2 >>> 16/ >>> 4 4 >>> Oefening. i, j, r = 8, 4, 0 r = i j r = ( i / j ) == i % j r = i < j or i > j 2.4 Enkele voorgedefinieerde functies Naast constanten en variabelen kunnen in expressies ook functie-oproepen voorkomen. In vorige voorbeelden werden reeds enkele functies gebruikt, namelijk raw_input, int en float. Daarnaast zijn er nog een aantal standaard functies: exit(status); abs(n); beëindigen van een programma absolute waarde (integer of float argument) Python voorziet in een heleboel functies die meestal gegroepeerd zijn in modules. De meest voor de hand liggende voorbeelden zijn wiskundige functies, gegroepeerd in de module math. Wanneer zo n functie gebruikt wordt in een programma, moet deze geïmporteerd worden. Dit kan op twee manieren gebeuren: 1. ofwel wordt uit de volledige module geïmporteerd: import math x = 1.0 y = math. cos (x) 12
13 bij het gebruik van de functie moet de module ook aangegeven worden: dit gebeurt met de dot notatie, de modulenaam gevolgd door een punt en dan de naam van de functie; 2. ofwel wordt uit de module een specifieke functie geïmporteerd: from math import cos x = 1.0 y = cos (x) bij het gebruik van de functie moet de modulenaam niet gespecificeerd worden. Indien meerdere functies moeten kunnen geïmporteerd worden, kunnen deze na elkaar gescheiden door komma s gespecificeerd worden (from math import sin,cos). Alle functies van een module importeren kan met from math import. In beide gevallen wordt voor het argument x (in radialen) de cosinus-waarde berekend en deze functiewaarde wordt toegekend aan de variabele y. Wiskundige functies uit de module math: float cos(x) cosinus float sin(x) sinus float tan(x) tangens float exp(x) exponentiële waarde float log(x) natuurlijk logaritme float log10(x) logaritme met grondtal 10 float pow(x, y) x tot de macht y float sqrt(x) vierkantswortel float floor(x) geheel getal net kleiner dan x float ceil(x) geheel getal net groter dan x float acos(x) boogcosinus float asin(x) boogsinus float atan(x) boogtangens Opgave. Schrijf een programma dat een tabel met cosinuswaarden afdrukt voor hoeken van 0 tot 360 met stappen van 30 graden. # costab.py : een tabel met cosinus waarden 2 import math def main ( ) : 4 graden = 0.0 print %7s %10s % ( x, cos (x) ) 6 print 18 while graden <= : 8 radialen = graden math. pi /180.0 y = math. cos ( radialen ) 10 print %7.1 f %10.4 f % ( graden, y) graden += # startoproep main () Resultaat: x cos(x) Omdat de voorgedefinieerde functie een argument in radialen verwacht, moet de hoek gegeven in graden, omgezet worden (πx/180). math.pi is een constante die gedefinieerd is in de module math met een waarde (benaderend) gelijk aan π: math. pi =
14 Om een mooi uitgelijnde tabel te krijgen, worden bij het print statement de format (%) operator gebruikt: de eerste operand is een formaatstring met daarin formaatsequenties die aangeven hoe de elementen van de tweede operand moeten geformatteerd worden. Het resultaat van de % operator is een string. Een formaatsequentie in een formaatstring (eerste operand van de format operator) geeft per element van de tweede operand aan hoe deze waarde moet geformatteerd worden: %d int waarde eventueel getal geeft veldbreedte aan %f float waarde eventueel eerste getal geeft veldbreedte aan eventueel tweede getal geeft aantal cijfers na de komma aan %s string waarde eventueel getal geeft veldbreedte aan Om in de tabel een lijntje te hebben onder de titel, wordt een operatie op de string - uitgevoerd (lijn 5): een vermenigvulding met 18 resulteert in een string bestaande uit 18 mintekens. 2.5 Begrippen Constanten, objecten, variabelen, identifiers, types. Expressies: rekenkundig, vergelijkend, logisch. Operatoren: unair en binair, prioriteit en associativiteit. Voorgedefinieerde functies. De format operator. 14
15 3 Controle structuren 3.1 Keuze statements Het if statement Om te kunnen laten beslissen of een statement al dan niet moet worden uitgevoerd, kan gebruik gemaakt worden van een keuze- of conditioneel statement. if expressie : statement1 else : statement2 Als de expressie een waarde verschillend van 0 (d.i. True) heeft, dan wordt statement1 uitgevoerd en statement2 niet. Wanneer de waarde van de expressie gelijk is aan 0 (d.i. False), dan wordt statement2 uitgevoerd en statement1 wordt overgeslagen. De expressie waarvan de waarde getest wordt, is meestal een logische expressie. Zowel statement1 als statement2 kunnen blok-statements zijn, zodat de algemene vorm ook als volgt weergegeven wordt: if expressie : statement statement... else : statement statement... In de volgende vorm is het else gedeelte weggelaten: if expressie : statement statement... Opgave. Lees een geheel getal en druk af of het even of oneven is. # even1.py: test of een ingelezen geheel getal even of oneven is 2 def main ( ) : invoer = raw input ( Geef een geheel getal : ) 4 getal = int ( invoer ) if getal%2 == 0 : 6 print getal, i s even else : 8 print getal, i s oneven # startoproep 10 main () De expressie in de if test hoeft niet een logische expressie te zijn. De waarde van een rekenkundige expressie kan ook gebruikt worden, waarbij een niet-nul waarde als True geïnterpreteerd wordt, en nul als False: # even2.py: test of een ingelezen geheel getal even of oneven is 2 def main ( ) : invoer = raw input ( Geef een geheel getal : ) 4 getal = int ( invoer ) if getal%2 : 6 print getal, i s oneven else : 8 print getal, i s even # startoproep 10 main () 15
16 Opgave. Schrijf een programma dat twee tijden in seconden inleest en de som afdrukt. Indien de som één minuut of meer is, moet dit afgedrukt worden. Indien de som één uur of meer is, moet dit afgedrukt worden. # tijd2.py: twee tijden in seconden inlezen, som afdrukken in uur:min:sec 2 def main ( ) : l i j n = raw input ( Geef twee tijden : ) 4 een, twee = l i j n. s p l i t () tijd1 = int ( een ) 6 tijd2 = int ( twee ) som = tijd1 + tijd2 8 if som < 60 : print de som i s, som, seconden 10 else : factor = som/60 12 if factor < 60 : print de som i s, factor, minuten en, som%60, seconden 14 else : print de som i s, factor /60, uren,, 16 print factor %60, minuten en, som%60, seconden # startoproep 18 main () De twee getallen worden op één lijn achter elkaar ingevoerd gescheiden door een spatie. Het resultaat van raw_input is een string bestaande uit cijfers en een spatie. Door middel van de split methode kan deze string opgesplitst worden in twee strings waarbij de spatie als scheidingsteken gebruikt wordt. Deze twee strings kunnen dan met de int functie omgevormd worden tot gehele getalwaarden. Wanneer een if statement gebruikt wordt binnen een if statement, moet duidelijk gemaakt worden waar de else bijhoort. # nestif1.py def main ( ) : a, b, c = 1, 2, 3 if a < b : if a < c : print klein, a else : print midden, a # startoproep main () # nestif2.py def main ( ) : a, b, c = 1, 2, 3 if a < b : if a < c : print klein, a else : print ergens, a # startoproep main () In Python is indentatie voldoende om de juiste blokstructuur aan te geven. In de testexpressie kan geen toekenning gebeuren. Dus het hiernaast staand if getal = 5 : fragment resulteert in een syntactische print getal fout: De expressie waarvan de waarde getest wordt, kan natuurlijk bestaan uit een aantal relationele expressies die met behulp van logische operatoren gecombineerd zijn: if getal >= 5 and getal <= 10 : print getal, in het interval [5,10] if getal < 5 or getal > 10 : 16
17 print getal, buiten interval [5,10] Dikwijls moet de verwerking opgesplitst worden in meerdere onderling exclusieve acties. Dit kan gebeuren met de elif constructie. Opgave. Schrijf een programma dat een aantal gehele getallen leest en telt hoeveel er kleiner zijn dan 10, hoeveel er gelegen zijn tussen 10 en 99, hoeveel tussen 100 en 999 en hoeveel tussen 1000 en Als de rij getallen ingegeven zijn, wordt ingegeven om het einde van de ingave aan te geven. 1 # freq.py: frequenties van ingelezen getallen def main ( ) : 3 print Geef een aantal gehele getallen, eindig met invoer = raw input ( getal : ) 5 getal = int ( invoer ) c i j f e r, tiental, honderdtal, duizendtal = 0, 0, 0, 0 7 while getal!= : if getal < 10 : 9 c i j f e r += 1 elif getal < 100 : 11 t i e n tal += 1 elif getal < 1000 : 13 honderdtal += 1 elif getal < : 15 duizendtal += 1 else : 17 pass invoer = raw input ( getal : ) 19 getal = int ( invoer ) print c i j f e r, tiental, honderdtal, duizendtal 21 # startoproep main () Merk op dat de laatste else gevolgd door het leeg statement (pass), evengoed kan weggelaten worden. Opgave. Schrijf een programma dat een cijfer inleest. Wanneer dit cijfer groter is dan nul en kleiner is dan 4, moet de bijhorende woordwaarde afgedrukt worden. Bij een andere waarde kan gewoon de melding cijfer afgedrukt worden. # cijfer.py: inlezen van een cijfer en afdrukken als woord 2 def main ( ) : invoer = raw input ( geef een c i j f e r : ) 4 c i j f e r = int ( invoer ) if c i j f e r == 1 : 6 print een elif c i j f e r == 2 : 8 print twee elif c i j f e r == 3 : 10 print drie elif c i j f e r >= 4 and c i j f e r <= 9 : 12 print c i j f e r else : 14 print dit i s geen c i j f e r, c i j f e r 17
18 # startoproep 16 main () Merk op dat er in vele andere talen een alternatieve constructie (switch) bestaat om een aantal verschillende gevallen van elkaar te onderscheiden. 3.2 Iteratie statements Opgave. Schrijf een programma dat 10 gehele getallen leest en daarvan de som afdrukt. # intsom2.py: tien gehele getallen inlezen en de som berekenen 2 # op een langdradige manier def main ( ) : 4 som = 0 invoer = raw input ( Geef een geheel getal : ) 6 getal = int ( invoer ) som += getal 8 invoer = raw input ( Geef een geheel getal : ) getal = int ( invoer ) 10 som += getal invoer = raw input ( Geef een geheel getal : ) 12 getal = int ( invoer ) som += getal 14 invoer = raw input ( Geef een geheel getal : ) getal = int ( invoer ) 16 som += getal invoer = raw input ( Geef een geheel getal : ) 18 getal = int ( invoer ) som += getal 20 invoer = raw input ( Geef een geheel getal : ) getal = int ( invoer ) 22 som += getal invoer = raw input ( Geef een geheel getal : ) 24 getal = int ( invoer ) som += getal 26 invoer = raw input ( Geef een geheel getal : ) getal = int ( invoer ) 28 som += getal invoer = raw input ( Geef een geheel getal : ) 30 getal = int ( invoer ) som += getal 32 invoer = raw input ( Geef een geheel getal : ) getal = int ( invoer ) 34 som += getal print de som van deze getallen i s, som 36 # startoproep main () Dit is duidelijk geen elegante oplossing. Het wordt nog veel erger wanneer bijvoorbeeld 100 getallen moeten gesommeerd worden. De meeste programmeertalen hebben hiervoor een aantal controle structuren voorzien waarmee het mogelijk is een herhaling (een iteratie) compact neer te schrijven. In deze contekst spreekt men dikwijls over een programma-lus. Python heeft twee iteratie-structuren. 18
19 3.2.1 Het while statement Een eerste structuur is reeds gebruikt geweest in enkele voorgaande programma s bijvoorbeeld bij het algoritme van Euclides (ggd.py). De algemene vorm is: while expressie : statement Zolang de expressie een waarde True (d.i. een waarde verschillend van 0) oplevert, wordt statement uitgevoerd. Dit statement is meestal een blok-statement: while expressie : statement1 statement2... volgend statement In sommige van deze statements gebeuren normaal aanpassingen aan verschillende variabelen zodat na een tijd de expressie de waarde False oplevert. Op dat moment wordt de lus verlaten en gaat het programma verder met de uitvoering van volgend_statement. 1 # wsom2.py: berekenen van de som van 10 getallen AANTAL = 10 3 def main ( ) : print Geef tien gehele getallen om te sommeren 5 t e l l e r = 0 som = 0 7 while t e l l e r < AANTAL : invoer = raw input ( getal : ) 9 getal = int ( invoer ) som += getal 11 t e l l e r += 1 print som van deze getallen i s, som 13 print gemiddelde van deze getallen i s, som/aantal # startoproep 15 main () Merk op dat voor het berekenen van het gemiddelde een deling van twee gehele getallen gebruikt wordt en dat de uitkomst dus ook een geheel getal is. De drie basiselementen die in een herhalingsstructuur voorkomen, zijn: 1. de initialisatie: de variabele teller krijgt een beginwaarde; 2. de test op het beëindigen van de lus: de variabele teller wordt vergeleken met een eindwaarde (AANTAL); 3. de stap: de variabele teller wordt aangepast, in dit geval verhoogd. In de while constructie ligt alleen de test op einde syntactisch vast. Omdat deze test gebeurt voordat enig statement in de lus uitgevoerd wordt, kan het zijn dat deze test reeds de eerste maal False oplevert, zodat de statements in de lus nooit zullen uitgevoerd worden. Om het programma gemakkelijk te kunnen aanpassen wanneer het aantal op te tellen getallen wijzigt, kan best voor dit aantal een aparte naam voorzien worden, die in het begin van het programma een waarde krijgt en in de rest van het programma niet gewijzigd wordt (een soort naamconstante). Voor de duidelijkheid wordt zo n naam in hoofdletters genoteerd. Bemerkingen. Wanneer voor de logische expressie bij de while de waarde 1 (True) gebruikt wordt, krijgt men een oneindige lus (links onderstaand fragment). Na de while moet minstens één statement in het blok staan. Eventueel kan dit een leeg statement (pass) zijn. Indien er geen blok (via indentatie) volgt zoals in het rechts staand fragment, resulteert dit in een syntactische fout. 19
20 t e l l e r = 0 while 1 : print t e l l e r t e l l e r += 1 AANTAL = 10 while t e l l e r < AANTAL : invoer = raw input ( Geef getal : ) getal = int ( invoer ) som += getal t e l l e r += Het for statement In een tweede iteratie-structuur wordt via een functie vastgelegd hoe de drie basiselementen van een lus (initialisatie, test op einde en de stap) gedefinieerd worden. De semantiek is volledig identiek aan het while statement. for i in range ( i n i t e x p r e s s i e, eind expressie, stap expressie ) : statement De functie range genereert een lijst van gehele getallen tussen de waarde van de init_expressie en de waarde van de eind_expressie(niet inbegrepen), met een increment gelijk aan de stap_expressie. Met de for... in constructie neemt de lusvariabele telkens de volgende waarde uit deze lijst aan, waarmee dan het statement uitgevoerd wordt. Ook hier kan statement een blok-statement zijn. # fsom2.py: berekenen van de som van 10 getallen 2 AANTAL = 10 def main ( ) : 4 print Geef tien gehele getallen om te sommeren som = for t e l l e r in range (AANTAL) : invoer = raw input ( getal : ) 8 getal = int ( invoer ) som += getal 10 print som van deze getallen i s, som print gemiddelde van deze getallen i s, som/aantal 12 # startoproep main () De variabele teller is in dit voorbeeld de lusvariabele. In tegenstelling tot vorig voorbeeld is nu som geïnitialiseerd met een float (0.0) en wordt een juister gemiddelde berekend. Het eerste en laatste argument bij de range functie kunnen weggelaten worden, beginwaarde wordt dan 0 en de stap is dan gelijk aan 1, bijvoorbeeld: for t e l l e r in range (3,AANTAL) : for t e l l e r in range (AANTAL) : Na de for moet weer minstens één statement in de lus staan, ofwel achter de dubbele punt, ofwel geïndenteerd in een blok. Een eventueel leeg statement kan ongewenste resultaten opleveren. Opmerking. De argumenten van de range functie kunnen expressies zijn. Maar wijzigingen op de betrokken variabelen in het blok van de lus hebben geen effect op het aantal maal dat de lus uitgevoerd wordt. De functie range genereert de lijst van gehele getallen voordat één statement van het blok van de lus uitgevoerd wordt. Begin- en eindwaarden van de lusvariabele kunnen zelf variabelen zijn. 1 # argrange. py: geen effect van wijzigen van range argumenten 20
21 def main ( ) : 3 a, b, c = 1, 12, 3 for t e l l e r in range (a, b, c ) : 5 print t e l l e r=, t e l l e r, a=, a, b=, b, c=, c a += 1 7 b = 1 c += 1 9 t e l l e r += 4 # startoproep 11 main () Ook een wijziging bij de lusvariabele in het blok heeft geen effect op de volgende doorgang in het blok Het break en continue statement In de twee lus-constructies is een break statement mogelijk. Het effect is dat de lus (voortijdig) verlaten wordt en dat de uitvoering verder gezet wordt na het lus statement. Hiermee kan een lus beëindigd worden met behulp van een test die niet in het begin van de lus staat maar ergens tussenin of op het einde. Daarnaast is er ook het continue statement. Er wordt dan meteen de test op beëindiging die bij de while hoort, uitgevoerd. Bij for wordt verder gegaan met het volgende element van de lijst die door de range functie gegenereerd is. Opgave. Schrijf een programma dat een aantal gehele getallen leest; dit aantal is ten hoogste 100. De positieve getallen moeten gesommeerd worden, negatieve getallen worden overgeslagen en wanneer een nul ingelezen wordt, moet gestopt worden. 1 # fsompos. py: sommeren van een aantal positieve getallen AANTAL = def main ( ) : print Geef een aantal gehele getallen ( nul om te stoppen ) 5 som = 0 for i in range (AANTAL) : 7 invoer = raw input ( getal : ) getal = int ( invoer ) 9 if getal < 0 : continue 11 if getal == 0 : break 13 som += getal print aantal ingelezen getallen i s, i 15 print som van de positieve getallen i s, som # startoproep 17 main () Merk op. Wanneer de for-lus in bovenstaand voorbeeld vervangen wordt door een while-lus is er een klein verschil in wat het programma doet (afhankelijk van waar de aanpassing van de lus-variabele gebeurt). Bij de for en while kan ook een else toegevoegd worden: 21
22 for i in range (5) : statement else : statement while expressie : statement else : statement Bij for wordt het blok bij de else uitgevoerd wanneer alle elementen van de lijst (gegenereerd door range) behandeld zijn. Bij while wordt het blok bij de else uitgevoerd wanneer de expressie niet meer waar is. Dus in beide gevallen is dit wanneer de lus beëindigd wordt op een normale manier. Het blok bij de else wordt echter niet uitgevoerd wanneer de lus voortijdig eindigt omdat in het lusblok een break uitgevoerd wordt. De else constructie bij een lus heeft dus enkel zin in combinatie met een break zoals in volgend voorbeeld geïllustreerd wordt. Opgave. Schrijf een programma dat een willekeurig geheel getal, in het interval [1,100] kiest, dat dan moet geraden worden. Als de gok groter is, dan meldt het programma te hoog. Als de gok kleiner is, dan meldt het programma te laag. Als de gok gelijk is aan het gekozen getal, dan moet het programma het aantal gedane pogingen afdrukken. Er mogen maximaal 10 gokpogingen gedaan worden. Hulp. Er is een module random beschikbaar met daarin functies die random getallen kunnen genereren De functie-oproep random.randint(1,100) geeft een willekeurig geheel getal in het interval [1,100]. # spel.py: raden van een getal tussen 1 en import random AANTAL = 10 4 def main ( ) : print Zoeken van een getal in het interval [1,100] 6 t e l l e r = 0 zoekgetal = random. randint (1,100) 8 gevonden = False while t e l l e r < AANTAL : 10 invoer = raw input ( gok : ) gok = int ( invoer ) 12 t e l l e r += 1 if gok == zoekgetal : 14 gevonden = True break 16 elif gok > zoekgetal : print Uw gok i s te hoog 18 else : print Uw gok i s te laag 20 else : print Maximum aantal gokken bereikt 22 i f gevonden : print Juist gegokt in, teller, pogingen 24 print te gokken getal i s, zoekgetal # startoproep 26 main () 22
23 3.3 Nog enkele voorbeelden. Opgave. Schrijf een programma dat een aantal gehele getallen leest en daarvan het gemiddelde en het grootste bepaalt en afdrukt. Als de rij getallen ingegeven zijn, wordt 999 ingegeven om het einde van de ingave aan te geven. Die 999 mag dus niet meegerekend worden voor gemiddelde of grootste. # gemid. py: gemiddelde van een aantal ingelezen getallen 2 def main ( ) : print Geef een aantal getallen (999 om te stoppen ) 4 t e l l e r = 0 som = grootste = 0.0 invoer = raw input ( getal : ) 8 getal = int ( invoer ) while getal!= 999 : 10 t e l l e r += 1 if getal > grootste : 12 grootste = getal som += getal 14 invoer = raw input ( getal : ) getal = int ( invoer ) 16 print grootste ingelezen getal i s, grootste print aantal ingelezen getallen i s, t e l l e r 18 gemiddelde = som/ t e l l e r print gemiddelde van de ingelezen getallen i s, gemiddelde 20 # startoproep main () Opgave. Bereken een benaderende waarde voor de bepaalde integraal van cos 2 (x) tussen a = 0.0 en b = 1.0. Gebruik voor de benadering de trapezium-regel: I = N i=1 (x i+1 x i ) f(xi)+f(xi+1) 2 = h ( f(a) 2 + N i=2 f(x i) + f(b) 2 ) met h = (b a)/n, x i+1 = x i + h en x 1 = a 1 # trapezium.py : benadering bepaalde integraal import math 3 EPS = 1.0E 4 5 def main ( ) : print n vorig integraal ; 7 print 32 n = 1 9 a = 0.0 b = vorig = 0.0 integraal = (b a ) (math. cos (a) math. cos (a) \ 13 + math. cos (b) math. cos (b ))/2.0 while abs ( ( vorig integraal )/ integraal ) > EPS : 15 vorig = integraal n = 2 23
24 17 stap = (b a)/n x = a 19 integraal = (math. cos (a) math. cos (a ))/2.0 i = 2 21 while i <= n : x += stap 23 integraal += (math. cos (x) math. cos (x )) i += 1 25 integraal += (math. cos (b) math. cos (b ))/2.0 integraal = stap 27 print %4d %s %12.7 f %12.7 f % (n,, vorig, integraal ) print print %4d %12.7 f %12.7 f % (n, vorig, integraal ) # startoproep 31 main () Wanneer een statement lang is en niet meer op één lijn kan, kan zo n statement gesplitst worden over meerdere lijnen. Hiervooor kan het splitsingsteken \ gebruikt worden. Het resultaat van dit programma: n vorig integraal Begrippen Exact: 1 0 cos2 xdx = [ x 2 ] cos x sin x = Keuze-controle-structuren: if en if-elif-else. Lus-controle-structuren: while en for. Voortijdig afbreken: break en continue. Blokstructuur: een programma is opgebouwd uit een aantal blokken, elk blok, behalve het hoofdblok heeft een hoofding: blok 0 hoofding : blok 1 hoofding : blok 2 blok 1 blok 0 24
25 4 Functies van eigen maak 4.1 Waarom zelfgedefinieerde functies 1. om programmagedeelten die meerdere keren voorkomen slechts éénmaal te schrijven, bijv. cos 2 x in vorig voorbeeld; 2. om zelf een aantal veelgebruikte functies ter beschikking te hebben; 3. om een probleem in kleinere deelproblemen op te splitsen. Deelproblemen zijn meer handelbaar en men hoeft alleen aan de oplossing van dat deelprobleem te denken. Een vuistregel. Een functie mag niet langer dan een 50-tal lijnen zijn (een afgedrukte versie op een blad papier geeft dan een goed overzicht). Volgens sommigen mag een functie slechts een 25-tal lijnen lang zijn zodat de volledige functie op één scherm te bekijken is. Naast herhalingen en keuzes verstoren functieoproepen het normale lineair verloop van de controle stroom doorheen een programma: statement 1. functie(). statement n def functie() : statement 1. routine(). return def routine() :. if voorwaarde : return else : return hoofdprogramma niveau 1 niveau Functies zonder parameters en terugkeerwaarde Meestal hebben functies een terugkeerwaarde, bijvoorbeeld de wiskundige functies uit de math module: y = math. cos (math. pi ) In sommige gevallen worden toch functies gedefinieerd die geen terugkeerwaarde hebben. In andere talen wordt zo n deelprogramma procedure of subroutine genoemd. Opgave. Op verschillende plaatsen in een programma moet een lijn bestaande uit 30 - tekens op het scherm komen. 1 # lijn.py: lijn met 30 mintekens LIJNLEN = 30 3 def l i j n () : i = 0 5 while i < LIJNLEN : print, 7 i += 1 print 9 def main ( ) : 11 print programma met een aantal l i jnen # een aantal statements 25
26 13 l i j n () # een aantal statements 15 l i j n () # een aantal statements 17 l i j n () 19 # startoproep main () De variabele i, in de functie lijn gedefinieerd, is een lokale variabele die alleen binnen de functie lijn kan gebruikt worden. 4.3 Functies met parameters maar geen terugkeerwaarde Wanneer er toch parameters zijn, worden de namen van deze parameters tussen de haakjes bij de functie definitie vermeld. Men spreekt van formele parameters. Bij de functie oproep worden tussen de haakjes de actuele argumenten gegeven. Elk van deze argumenten is een expressie. Deze wordt geëvalueerd tijdens de oproep en de resulterende waarde (r-value) wordt gebruikt om de corresponderende formele parameter te initialiseren. Opgave. Zelfde probleem als hiervoor maar de lijn is niet overal even lang. # vlijn. py: lijn met variabel aantal mintekens 2 LIJNLEN = 30 def l i j n ( lengte ) : 4 i = 0 while i < lengte : 6 print, i += 1 8 print 10 def main ( ) : print programma met een aantal l i jnen 12 # een aantal statements print l i j n van l i j n (20) # een aantal statements 16 print l i j n van, LIJNLEN l i j n (LIJNLEN) 18 # een aantal statements print l i j n van, LIJNLEN/2 20 l i j n (LIJNLEN/2) 22 # startoproep main () Net zoals de lokale variabele i binnen de functie lijn, is de parameter lengte alleen binnen de functie lijn gekend. 4.4 Functies met een functie-(return)-waarde Zoals hierboven reeds vermeld hebben de meeste functies een terugkeerwaarde. 26
27 Wanneer een functieoproep in een expressie voorkomt, zal de resulterende waarde van de functie gebruikt worden om de expressie te evalueren. Men kan de () van de oproep zien als een unaire operator die toegepast wordt op de functienaam. Deze operator heeft een zeer hoge prioriteit. Opgave. Schrijf een programma dat een grondtal en een (niet-negatieve, gehele) exponent inleest en aan de hand van een functie de macht (grondtal tot de macht exponent) berekent. 1 # macht. py: bereken grondtal tot de macht ( gehele) exponent def macht( grondtal, exponent) : 3 i = 0 functiewaarde = while i < expo nent : functiewaarde = grondtal 7 i += 1 return functiewaarde 9 def main ( ) : 11 print machtsberekening invoer = raw input ( r e e e l grondtal : ) 13 grondtal = f l o at ( invoer ) invoer = raw input ( gehele exponent : ) 15 exponent = int ( invoer ) resultaat = macht( grondtal, exponent) 17 print grondtal exponent, resultaat 19 # startoproep main () In een expressie berekening = macht (2.4, 5) zal eerst de functie macht uitgevoerd worden. Het resultaat hiervan zal vermenigvuldigd worden met 7.0 en hierbij zal 5.0 opgeteld worden. Deze uiteindelijke waarde zal dan toegekend worden aan de variabele berekening. De operator (), d.i. de oproep van de functie, heeft dus een hogere prioriteit dan * en +. De terugkeer vanuit een functie naar de oproep hoeft niet op het einde van de functie te gebeuren. Het return statement kan om het even waar in de functie staan. 4.5 Voorbeelden van gebruik van functies Een standaard functie: 1 # fsin. py : voorbeeld van gebruik van een standaardfunctie from math import s i n # invoegen van de functie definitie 3 from math import pi # invoegen van de constante 5 def main ( ) : x = pi / 6 # dertig graden 7 y = sin (x) # functie oproep */ print De sinus van dertig graden i s, y 9 # startoproep 11 main () 27
28 Een zelfgedefinieerde functie: 1 # fbtw.py : voorbeeld van gebruik van een zelf- gedefinieerde functie 3 def btw21(a) : # functie-definitie b = a # de 0.5 is voor de afronding 5 return int (b) 7 def main ( ) : invoer = raw input ( Geef het faktuurbedrag : ) 9 faktuurbedrag = int ( invoer ) btw = btw21( faktuurbedrag) # functie-oproep 11 i n c l u s i e f = faktuurbedrag + btw print BTW =, btw 13 print i n c l u s i e f btw =, i n c l u s i e f 15 # startoproep main () 4.6 Geheugenklassen Lokaal. Variabelen die in een functie benoemd worden, zijn by default lokale variabelen. Bij de eerste toekenning wordt een object met deze waarde gemaakt, dus wordt geheugen toegewezen, en krijgt dit object een naam. Deze variabelen zijn alleen binnen dat blok gedefinieerd en gekend. Na het verlaten van dat blok is het object niet meer bereikbaar via deze lokale variabele. Globaal. Om informatie over de grenzen van blokken of functies heen te kunnen uitwisselen maakt men gebruik van functieparameters. In uitzonderlijke gevallen kan men gebruik maken van van globale variabelen. Zo n variabele wordt buiten een functie gedeclareerd, en er wordt permanent geheugenruimte aan toegewezen. In de functie wordt deze variabele bereikbaar gemaakt door deze als global te benoemen. Voorbeeld: # scope.py : globale en lokale variabelen 2 def f () : 4 global b a = 15 6 b = 17 print in de functie a i s, a, en b i s, b 8 def main ( ) : 10 print in het hoofdprogramma a i s, a, en b i s, b f () 12 print na de functieoproep a i s, a, en b i s, b 14 # startoproep a = 5 16 b = 7 main () Dit programma geeft de volgende output: 28
29 in het hoofdprogramma is a = 5 b = 7 in de functie is a = 15 b = 17 na aanroep van de functie f is a = 5 b = 17 Wanneer het programma start, en er is alleen een variabele als global benoemt in een functie, dan is deze variabele onbestaande totdat de functie opgeroepen wordt. Argumenten en parameters. Tijdens de oproep van een functie worden de formele parameters in de functie-definitie geïnitialiseerd met de waarde van de argumenten die in het oproep-statement staan. 1 # pararg.py : argumenten en parameters 3 def f (a, b) : d = a + b 5 a = 1 b = 2 7 c = 3 print in de functie a i s, a, b i s, b, en c i s, c 9 return d 11 def main ( ) : a = 5 13 b = 6 c = 7 15 print voor eerste functieoproep a i s, a, b i s, b, en c i s, c c = f (a, b) 17 print na eerste functieoproep a i s, a, b i s, b, en c i s, c a = f (b, c ) 19 print na tweede functieoproep a i s, a, b i s, b, en c i s, c 21 # startoproep main () Dit programma geeft als output: voor aanroep van de functie zijn a = 5, b = 6 en c = 7 in de functie zijn a = 1, b = 2 en c = 3 na aanroep van de functie zijn a = 5, b = 6 en c = 11 in de functie zijn a = 1, b = 2 en c = 3 na aanroep van de functie zijn a = 17, b = 6 en c = Een functie met meerdere resultaten Argumenten die bij een functieoproep doorgegeven worden aan de formele parameters, worden gebruikt als initialisatie van deze formele parameters. In de functie kunnen deze formele parameters van waarde wijzigen. Maar dit heeft geen effect op de waarden van de argumenten nadat de functie uitgevoerd is. Opgave. Schrijf een programma dat via een functie de waarden van twee variabelen omwisseld. # wissel1.py: twee waarden wisselen via een functie 2 def wissel (x, y) : h = x 29
30 4 x = y y = h 6 def main ( ) : 8 a, b = 5, 8 print voor de functieoperoep : a =, a, en b =, b 10 wissel (a, b) print na de functieoperoep : a =, a, en b =, b 12 # startoproep 14 main () Dit programma drukt af: voor de functieoproep is a = 5 b = 8 na de functieoproep is a = 5 b = 8 De variabelen in het hoofprogramma zijn dus niet gewijzigd. De enige manier om deze variabelen te laten wijzigen op basis van berekeningen in de functie is via de terugkeerwaarde. Omdat in Python meerdere variabelen langs de linkerkant in de toekenning kunnen geschreven worden, is het mogelijk om meerdere terugkeerwaarden te specificeren bij de return. # wissel2.py: twee waarden wisselen via een functie 2 def wissel (x, y) : return y, x 4 def main ( ) : 6 a, b = 5, 8 print voor de functieoperoep : a =, a, en b =, b 8 a, b = wissel (a, b) print na de functieoperoep : a =, a, en b =, b 10 # startoproep 12 main () Dit programma drukt af: Voor de functieoproep is a = 5 b = 8 Na de functieoproep is a = 8 b = Een probleem in deelproblemen opsplitsen Opgave. Schrijf een programma dat de coëfficiënten van een vierkantsvergelijking inleest en de oplossingen van deze vierkantsvergelijking afdrukt. Beschouw alle gevallen! # vkv. py oplossen van een vierkantsvergelijking 2 import math 4 def l i n e a i r (a, b) : if a!= 0 : 6 print l i n e a i r e vgl met wortel, b/a else : 8 if b!= 0 : print valse vergelij king 30
31 10 else : print identieke v er gelijking 12 def vkv (a, b, c ) : 14 x1 = rat (a, b) d = b a c 16 if d == 0.0 : print dubbele wortel, x1 18 elif d > 0.0 : x2 = i r r a t (a, d) 20 print twee r e e l e wortels, x1+x2, x1 x2 else : 22 x2 = i r r a t (a, d) print twee complexe wortels, x1, +j, x2, x1, j, x2 24 def rat (a, b) : 26 return b/2.0/a 28 def i r r a t (a, d) : return math. sqrt (d)/2.0/ a 30 def main ( ) : 32 invoer = raw input ( Geef kwadraatscoef : ) a = f l o a t ( invoer ) 34 invoer = raw input ( Geef l i n e a i r e coef : ) b = f l o a t ( invoer ) 36 invoer = raw input ( Geef constante coef : ) c = f l o a t ( invoer ) 38 if a!= 0.0 : vkv(a, b, c ) 40 else : l i n e a i r (b, c ) 42 # startoproep 44 main () 4.9 Leesoefening. Opgave. Leg de werking van volgend programma uit; wat wordt er uitgeschreven? # funpri.py : oproepen van een functie in een expressie 2 def fun (x, y) : h = x 4 x = y y = h 6 print x =, x, y =, y return x y + h 8 def main ( ) : 10 a = 7 b = 2 12 r = fun (a, b) 31
32 print a =, a, b =, b, en r =, r 14 r = a + fun (a, b) + b print a =, a, b =, b, en r =, r 16 # startoproep 18 main () 4.10 Begrippen Functies: oproep f() f(n) y = f(x) definitie def f() : def f(m) : def f(y) : return... m... r =...y return return r Returnwaarde, parameters en argumenten. Geheugenklassen: lokaal, globaal. Belangrijke opmerking. Opdat een functie algemeen bruikbaar zou zijn, mag een functie, tenzij in uitzonderlijke gevallen, van geen globale variabelen gebruik maken. D.w.z. alle variabelen in een functie moeten lokaal in die functie gedeclareerd zijn of via argumenten naar parameters doorgegeven worden. 32
33 5 Arrays 5.1 Waarom arrays Opgave. Schrijf een programma dat 5 gehele getallen leest en in omgekeerde volgorde terug afdrukt. # keerom1. py: vijf getallen inlezen en in omgekeerde volgorde afdrukken 2 def main ( ) : print Geef v i j f getallen 4 a = int ( raw input ( getal 1: )) b = int ( raw input ( getal 2: )) 6 c = int ( raw input ( getal 3: )) d = int ( raw input ( getal 4: )) 8 e = int ( raw input ( getal 5: )) print e, d, c, b, a 10 # startoproep 12 main () Het bovenstaand programma is geen stijlvol programma. Er worden vijf verschillende variabelen gebruikt voor iets dat vanuit het probleemdomein als één rij getallen bestempeld wordt. Daarnaast is de oplossing ook onbruikbaar wanneer het over meer getallen (bijvoorbeeld 100) gaat. 5.2 Een lijst Een list (lijst) is een opeenvolging van waarden. Deze waarden in de lijst worden elementen (items) genoemd en hebben elk een eigen type, bijv. een geheel getal, een reëel getal maar ook een lijst. Een lijst kan gecreëerd worden door de verschillende elementen op te sommen en te omsluiten door vierkante haakjes: k = [1, 2, 3, 4, 5, 6, 7] x = [ 2.0, 3.0, 4. 0] a = [ [ 1, 2 ], [ 3, 4 ], [ 5, 6] ] l = [ ] a is een geneste lijst en l is de lege lijst. Individele elementen in de lijst kunnen aangesproken worden via een index: een geheel getal, waarbij het eerste element van de lijst index 0 heeft. Een index groter of gelijk aan het aantal elementen in de lijst geeft een fout en met een negatieve index kan van achter naar voor geteld worden. print x # volledige lijst print x [ 1 ] # 3.0 print k [ 0 ], k[ 1] # 1 7 print a [ 1 ], a [ 1 ] [ 0 ] # [3,4] 3 In plaats van een gegeven lijst, zal in de meeste toepassingen een lijst opgebouwd worden op basis van invoerwaarden of berekeningen. Om een element achteraan aan een lijst toe te voegen kan de append methode gebruikt worden. Deze methode wordt geïllustreerd in een lijstgebaseerd programma voor voorgaand probleem: # keerom2. py: vijf getallen inlezen en in omgekeerde volgorde afdrukken 2 AANTAL = 5 def main ( ) : 4 l i j s t = [ ] print Geef, AANTAL, v i j f getallen : 33
34 6 for i in range (AANTAL) : invoer = raw input ( str ( i )+ : ) 8 l i j s t. append ( int ( invoer ) ) i = AANTAL 1 10 while i >= 0 : print l i j s t [ i ], 12 i = 1 print 14 # startoproep 16 main () De functie str zet het getal dat als argument meegegeven wordt, om in een string. Aan deze string wordt een tweede string aangeplakt met behulp van de + operator. Het geheel wordt dan als prompt uitgeschreven door de raw_input functie. 5.3 Numeric Python In technisch-wetenschappelijke toepassingen wordt gewerkt met vectoren en matrices: lijsten van gerelateerde waarden van hetzelfde type, gehele, reële of complexe getallen. Men zou hiervoor het list type van Python kunnen gebruiken. Maar een aantal veelvoorkomende operaties op vectoren en matrices vragen veel ruimte en tijd wanneer deze gedaan worden met de standaard datastructuren zoals lijsten. Een oplossing hiervoor is de Numeric Python (NumPy) uitbreiding, een module met een heleboel gereedschappen om verzamelingen van objecten georganiseerd in roosterachtige schema s, zoals vectoren en matrices, efficiënt te manipuleren. De werking van deze gereedschappen is vrij gelijkaardig aan de werking van matrix-talen zoals APL en MATLAB. In de volgende subsecties worden een aantal elementen uit de NumPy module gebruikt om manipulaties op een- en twee-dimensionale arrays te doen. Hierbij worden niet alle specifieke mogelijkheden gebruikt, maar worden de bewerkingen geprogrammeerd op een manier vergelijkbaar met andere programmeertalen, zoals C, Java, Een-dimensionale arrays Een array is een object data-type en kan gezien worden als een rij waarvan de elementen allemaal met dezelfde naam maar elk met een eigen volgnummer worden aangeduid. Alle elementen zijn van hetzelfde data-type en niet-leeg. In een technisch-wetenschappelijke omgeving wordt zoiets een vector genoemd. Elk element in de array kan gedurende de levensduur van de array gewijzigd worden. De lengte van een array is gelijk aan het aantal elementen. Deze lengte kan niet wijzigen gedurende de levensduur van de array. Er kunnen dus geen elementen worden toegevoegd aan of verwijderd uit de array. Een array kan gecreëerd worden door gebruik te maken van de array() functie. Het eerste argument is een list of tuple van waarden. Het aantal in deze lijst bepaalt de lengte van de array. Het eventuele tweede argument geeft het type van de elementen aan. Indien dit argument niet gegeven is, bepaalt Python zelf het type. Dit type bepaalt de grootte van elk element (itemsize). >>> x = array ([1, 2, 3 ] ) # list >>> x array ([1, 2, 3]) >>> print x [1 2 3] >>> y = array (( 0.5, 0.0, 0.5, 1.0), f l o a t ) # tuple >>> print y 34
35 [ ] >>> print y. size 4 >>> y. itemsize 8 De verschillende elementen in de array y kunnen aangesproken worden met de index [] operator: y[0], y[1], y[2], y[3] Alhoewel de lengte van de array 4 is, is er geen element y[4] omdat de rangnummer bij 0 begint. Bij het gebruik van een array-element y[i] wordt i de index of subscript genoemd. Deze index kan een constante, een variabele of een expressie zijn. De waarde van de index moet wel een geheel getal zijn, groter of gelijk aan nul en kleiner dan het aantal elementen in de array. De waarde van de index kan ook negatief zijn, waarbij de absolute waarde van de kleinste negatieve waarde gelijk moet zijn aan het aantal elementen in de array. Bij een negatieve index wordt van achteraan in de array geteld. Technieken om een vector van een bepaalde lengte te creëren: vector met gehele getallen: met een variante van de range functie; vector met alle elementen gelijk aan 0: zeros waarbij het eerste argument met behulp van een lijst de lengte aangeeft en het tweede argument het type; vector met alle elementen gelijk aan 1: ones waarbij het eerste argument met behulp van een lijst de lengte aangeeft en het tweede argument het type. >>> z = arange (10) >>> print z [ ] >>> print z [ 2 ], z [ 2] 2 8 >>> nul = zeros ( [ 7 ], int ) >>> print nul [ ] >>> een = ones ( [ 6 ], float ) >>> print een [ ] Aangezien een array een object is, moet een toekenning gezien worden als het geven van een naam aan dat object. De naam is een aanduiding van of een referentie naar het object. Wanneer door een toekenningsstatement zo n naam gecopieerd wordt naar een tweede naam, dan is deze tweede naam een alias voor hetzelfde object, deze naam refereert dus naar datzelfde object. Wanneer een element in het object gewijzigd wordt door gebruik te maken van de eerste naam, dan zal deze wijziging ook te zien zijn, wanneer het object aangesproken wordt door de tweede naam. >>> a = array ( [ 1.0, 3.0, 5. 0] ) >>> b = a >>> b [ 1 ] += 3.0 >>> print a=, a, b=, b a= [ ] b= [ ] De naam van de array zelf kan niet zomaar in om het even welke expressie gebruikt worden. Deze naam is een referentie naar een object (een aantal geheugenplaatsen) en kan dus niet gezien worden als een gewone variabele die één enkele geheugenplaats aanduidt. De rekenkundige operator + bijvoorbeeld kan wel gebruikt worden om de inhoud van twee geheugenplaatsen op te tellen. Het 35
36 resultaat kan dan met het toekenningsstatement (=) toegewezen worden aan een derde variabele (geheugenplaats). c = a + b ; Wanneer a, b en c arrays zijn, elk bijvoorbeeld van lengte 5, gaan we bovenstaande rekenkundige operatie voorlopig NIET gebruiken. De optelling van twee arrays kan best element per element gebeuren: 1 # arsom. py: optellen van twee arrays from numpy import array, zeros 3 def main ( ) : a = array ( [ 1. 0, 2.0, 3.0, 4.0, 5. 0 ] ) 5 b = array ( [ 1. 0, 2.0, 3.0, 4.0, 5. 0 ] ) c = zeros ( [ 5 ], f l o a t ) 7 for i in range ( len (a )) : c [ i ] = a [ i ] + b [ i ] 9 print a, +, b, >, c 11 # startoproep main () De expressie a == b waarbij a en b namen van arrays zijn, is syntactisch wel correct maar wordt semantisch anders geïnterpreteerd dan waarschijnlijk bedoeld is. Deze expressie gaat niet na of de twee arrays dezelfde elementen bevatten. De gelijkheid van twee arrays nagaan kan weer best element per element gebeuren: # arvgl. py: vergelijken van twee arrays 2 from numpy import array def main ( ) : 4 a = array ( [ 1. 0, 2.0, 3.0, 4.0, 5. 0 ] ) b = array ( [ 1. 0, 2.0, 3.0, 4.0, 5. 0 ] ) 6 g e l i j k = True for i in range ( len (a )) : 8 if a [ i ]!= b [ i ] : g e l i j k = False 10 break print a [ i ], b [ i ] 12 if g e l i j k : print de twee arrays bevatten dezelfde waardes else : print de twee arrays z i jn verschillend 14 # startoproep 16 main () Na de lus kan de variabele gelijk getest worden. Wanneer deze gelijk is aan 1, zijn de twee arrays gelijk, in de betekenis dat de waarden in de corresponderende elementen gelijk zijn. Merk op dat in het programma een kortsluitingsprincipe kan ingebouwd worden. Na het vinden van een eerste index waarbij de twee elementen niet gelijk zijn, hoeven de volgende elementen niet meer vergeleken te worden. 5.5 Functies met arrays als argumenten Wanneer een functie met parameters opgeroepen wordt, worden de waarden van de actuele argumenten doorgegeven naar de formele parameters: de waarden van de actuele argumenten worden gebruikt als initialisatie voor de formele parameters. 36
37 In de functie zelf worden de formele parameters gebruikt als operands in de expressies. Deze formele parameters kunnen daarbij van waarde veranderen. Maar wanneer de functie uitgevoerd is en verlaten wordt (via return), worden deze eventuele aangepaste waarden van de formele parameters NIET teruggecopieerd naar de actuele argumenten in de oproep. # param.py : het gedrag van parameters 2 import numpy 4 def kwadar(x, y, n) : x = x x 6 for i in range (n) : y [ i ] = y [ i ] y [ i ] 8 return x 10 def main ( ) : n = a = 5 b = numpy. zeros ( [ n ], int ) 14 for i in range (n) : b [ i ] = i 16 print Voor oproep van de functie, a print en de r i j b bevat :, 18 for i in range (n) : print b [ i ], 20 print res = kwadar(a, b, n) 22 print Na oproep van de functie, a, met resultaat, res print en de r i j b bevat :, 24 for i in range (n) : print b [ i ], 26 print 28 # startoproep main () Dit programma drukt af: Voor oproep van de functie 5 en de rij b bevat : Na oproep van de functie 5 met resultaat 25 en de rij b bevat : De waarde van a wordt doorgegeven naar de formele parameter x. In de functie kwadar wordt deze x gewijzigd. Maar na terugkeer is a niet gewijzigd. Uit het resultaat kan opgemaakt worden dat dit niet geldt voor de array b. Een array is in feite een list, één van de basisobjecttypes van Python. De naam van zo n object (tot hiertoe variabele genoemd), is een aanduiding van of referentie naar dit object. Wanneer zo n naam als argument doorgegeven wordt naar een parameter in een functie, dan wordt niet de volledige array gecopieerd. Maar door het doorgeven wordt de formele parameter een tweede naam (een bijkomende referentie) naar datzelfde object, net zoals bij een toekenning. Dus in de functie kwadar refereert deze formele parameter y naar dezelfde array als het argument b in de oproep. Omdat de formele parameter refereert naar de originele rij, zal elke wijziging die in de functie door middel van de formele parameter gebeurt, uitgevoerd worden op deze originele rij. Opgave. Een rij getallen in omgekeerde volgorde uitschrijven met behulp van functies. 37
38 1 # keerom3. py: getallen inlezen en in omgekeerde volgorde afdrukken import numpy 3 def l e e s r i j (x,m) : print Geef een aantal gehele getallen 5 for i in range (m) : invoer = raw input ( str ( i )+ : ) 7 x [ i ] = int ( invoer ) 9 def drukrij ( r,m) : for i in range (m) : 11 print r [m i 1], print 13 def main ( ) : 15 invoer = raw input ( Geef aantal : ) m = int ( invoer ) 17 a = numpy. zeros ( [m], int ) l e e s r i j (a,m) 19 drukrij (a,m) 21 # startoproep main () 5.6 Meer-dimensionale arrays In veel toepassingen heeft men te maken met een tabel, soms ook matrix genoemd. In Python kan dit gerealiseerd worden met een lijst, waarbij elk element in deze lijst op zich een lijst is. Bij de definitie van de variabele kan deze geïnitialiseerd worden: a = [ [1, 2], [2, 3], [3, 4] ] Net zoals bij eendimensionale arrays voorziet de module numpy een aantal functies waarmee op een klassiek wetenschappelijk-technische manier met matrices kan gewerkt worden. import numpy a = numpy. ones ( [MAXRIJ,MAXKOLOM], int ) b = numpy. zeros ( [MAXRIJ,MAXKOLOM], f l o at ) c = numpy. identity (3) Met de functie ones wordt een matrix gemaakt, waarbij de elementen van het type zijn, gegeven door het tweede argument. Deze elementen krijgen de waarde 1. Het eerste argument geeft aan hoeveel rijen (eerste getal in de lijst) en hoeveel kolommen (tweede getal in de lijst) er zijn. De functie zeros maakt op een gelijkaardige manier een matrix, maar nu worden de elementen geïnitialiseerd met 0. Met de functie identity wordt een vierkante identiteitsmatrix gemaakt, waavan de elementen van type float zijn. Wanneer MAXRIJ gelijk is aan 3 en MAXKOLOM gelijk aan 2 geeft dit de volgende matrix a[0][0] a[0][1] a[1][0] a[1][1] a[2][0] a[2][1] Deze matrix wordt in het werkgeheugen echter gestockeerd als één lange rij van opeenvolgende elementen: 38
39 a[0][0] a[0][1] a[1][0] a[1][1] a[2][0] a[2][1] Dit kan gezien worden als een rij van elementen waarin elk element op zich een rij is (zie korte inleiding op list). Opgave. Construeer een matrix waarin elk element gelijk is aan de som van de rij-index en de kolom-index en druk deze matrix af. # matrix.py: matrix met mat[i][j] = i+j 2 import numpy MAXRIJ = 3 4 MAXKOLOM = 5 6 def drukmat(x,m, n) : for i in range (m) : 8 for j in range (n) : print %4d % (x [ i ] [ j ] ), 10 print 12 def main ( ) : a = numpy. zeros ( [MAXRIJ,MAXKOLOM], int ) 14 for r i j in range (MAXRIJ) : for kolom in r a ng e (MAXKOLOM) : 16 a [ r i j ] [ kolom ] = r i j + kolom drukmat( a, MAXRIJ,MAXKOLOM) 18 # startoproep 20 main () De geconstrueerde matrix heeft volgende inhoud: en wordt in het werkgeheugen als één lange rij gestockeerd: Bij een functieoproep zal de de formele parameter een referentie bevatten naar dezelfde matrix als aangeduid door het actuele argument net zoals bij een een-dimensionale array. Dus wijzigingen in de matrix via de formele parameter in de functie, zijn zichtbaar in het blok dat de functie opgeroepen heeft met een actueel argument. 5.7 Uitgewerkte voorbeelden Priemgetallen Opgave. Schrijf een programma met functies dat met behulp van de zeef van Eratosthenes alle priemgetallen kleiner dan 1000 afdrukt (alle niet-priemgetallen worden weggezeefd). # zeef.py zoeken van priemgetallen ( Erathostenes) 2 from numpy import 4 def schrap ( zeef, p, n) : i = 2 p 39
40 6 while i <n : zeef [ i ] = 0 8 i += p 10 def main ( ) : invoer = raw input ( Geef maximum voor priemgetallen : ) 12 n = int ( invoer ) zeef = ones ( [ n ], int ) 14 zeef [ 0 ] = 0 zeef [ 1 ] = 0 16 for i in range (2,n) : if zeef [ i ] == 1 : 18 print i schrap ( zeef, i, n) 20 # startoproep 22 main () Driehoek van Pascal Opgave. Schrijf een programma met functies dat de driehoek van Pascal afdrukt tot op rij n, waarbij n in te lezen is. Een eerste functie moet n inlezen, een tweede functie moet de driehoek maken en een derde functie moet de driehoek afdrukken. (a + b) n = ( n 0 ) a n b 0 + ( n 1 ) a n 1 b 1 + De coëfficiënten worden als volgt berekend: ( ) n + 1 = k ( n 2 ) a n 2 b ( ) n k + ( ) n k 1 ( ) n a 1 b n 1 + n 1 # pascal. py: genereren van driehoek van Pascal 2 import numpy MAX = 20 4 def leesdimensie () : 6 while True : invoer = raw input ( Geef dimenstie [ 1.. +str (MAX)+ ] : ) 8 n = int ( invoer ) if n < MAX : 10 break return n 12 def maakdriehoek (a, n) : 14 for i in range (0,n+1) : a [ i ] [ 0 ] = 1 16 a [ i ] [ i ] = 1 for i in range (2,n+1) : 18 for j in range (1, i ) : a [ i ] [ j ] = a [ i 1][ j 1] + a [ i 1][ j ] 20 def printdriehoek (a, n) : 22 for i in range (n+1) : ( ) n a 0 b n n 40
41 print %2d % ( i ), :, 24 for j in range ( i +1) : print %4d % (a [ i ] [ j ] ), 26 print 28 def main ( ) : n = leesdimensie () 30 a = numpy. zeros ( [ n+1,n+1], int ) maakdriehoek (a, n) 32 printdriehoek (a, n) 34 # startoproep main () Het resultaat voor n = 6: Matrix-product 0: 1 1: 1 1 2: : : : : Opgave. Schrijf een programma dat twee matrices inleest, het matrix product berekent en afdrukt. 1 # matprod.py matrixproduct C = A x B import numpy 3 MAX = 20 5 def leesdimensie () : while True : 7 invoer = raw input ( Geef dimenstie [ 1.. +str (MAX)+ ] : ) n = int ( invoer ) 9 if n < MAX : break 11 return n 13 def inwendigproduct (a, b, r, k, l ) : som = for j in range ( l ) : som += a [ r ] [ j ] b [ j ] [ k ] 17 return som 19 def maakproduct(a, b, c, ar1, ak1, ak2) : for r in range ( ar1 ) : 21 for k in range ( ak2) : c [ r ] [ k ] = inwendigproduct (a, b, r, k, ak1) 23 def printmatrix (x,m, n) : 25 for i in range (m) : for j in range (n) : 41
42 27 print %9.4 f % (x [ i ] [ j ] ), print 29 def leesmatrix (x,m, n) : 31 for i in range (m) : for j in range (n) : 33 invoer = input ( element +str ( i )+, +str ( j)+ : ) x [ i ] [ j ] = float ( invoer ) 35 def main ( ) : 37 invoer = raw input ( aantal r i jen van eerste matrix ) ar1 = int ( invoer ) 39 invoer = raw input ( aantal kolommen van eerste matrix ) ak1 = int ( invoer ) 41 a = numpy. zeros ( [ ar1, ak1 ], f l o at ) leesmatrix (a, ar1, ak1) 43 invoer = raw input ( aantal kolommen van tweede matrix ) ak2 = int ( invoer ) 45 b = numpy. zeros ( [ ak1, ak2 ], f l o at ) leesmatrix (b, ak1, ak2) 47 c = numpy. zeros ( [ ar1, ak2 ], f l o at ) maakproduct(a, b, c, ar1, ak1, ak2) 49 printmatrix (a, ar1, ak1) printmatrix (b, ak1, ak2) 51 printmatrix (c, ar1, ak2) 53 # startoproep main () 5.8 Begrippen List: basiselementen: initialisatie, index [], append. Numpy: een- en meer-dimensionale arrays. Namen en objecten: toekenning en argument bij een functieoproep. 42
43 6 Interne voorstelling, types en conversies 6.1 Voorstelling van gegevens: bits en bytes Een (digitale) computer werkt steeds met binaire grootheden. De reden daartoe is het feit dat de computer bestaat uit een aantal onderdelen die slechts twee toestanden kunnen aannemen (bistabiele elementen; vb: flip-flop-schakelingen). De ene toestand wordt conventioneel voorgesteld als 1 en de andere als 0. Gewoonlijk wordt dit aangeduid door de technische term BIT (BInary digit = binair cijfer). Een bit is dus de kleinst mogelijke informatie-eenheid in een computersysteem. Bits dienen als bouwstenen voor grotere betekenisvolle informatiehoeveelheden. Elke vorm van informatie wordt gemanipuleerd in de vorm van een combinatie van enen en nullen. Het geheugen wordt ingedeeld in een aantal gebieden van gelijke grootte. Een gebied van 8 bits noemt men een byte. (Een nible is een groep van 4 bits). Een (computer)woord bestaat, afhankelijk van de computer architectuur, uit een 2 bytes (16 bits), 4 bytes (32 bits) of 8 bytes (64 bits). Het geheugen kan men voorstellen als een opeenvolging van vakken die elk uit 8 bits of één byte bestaan. Iedere geheugenplaats heeft een welbepaalde unieke identificatie (volgnummer) die men adres noemt. In het geheugen moeten programma en data gestockeerd worden. De grootte van een geheugen wordt meestal aangeduid in Kb, Mb of Gb. 1 Kb = 1 kilobyte = 2 10 bytes = 1024 bytes 1 Mb = 1 megabyte = 2 20 bytes = bytes 1 Gb = 1 gigabyte = 2 30 bytes = bytes 6.2 Binaire en andere talstelsels In het ons vertrouwde decimale talstelsel wordt als grondtal de waarde 10 genomen. Afhankelijk van de positie van een cijfer in een getal, wordt de waarde ervan bepaald = In dit talstelsel zijn tien verschillende cijfers nodig. In het binaire talstelsel is het grondtal 2 en zijn er maar twee cijfers nodig: de 0 en de 1 (bit) = MSB LSB getal 107 letter k Een getal in binaire voorstelling is meestal erg lang. Om een wat handiger voorstelling te hebben, kan men gebruik maken van het octale talstelsel met grondtal 8 of het hexadecimale talstelsel met grondtal 16. De omzetting van een binair getal naar een octaal getal kan vrij eenvoudig gebeuren door vanaf de LSB (least significant bit) de bits samen te nemen in groepjes van drie. Bij een hexadecimaal getal zijn dit groepjes van vier bits b In het octale talstelsel gebruikt men de cijfers van 0 tot 7. Bij het hexadecimale talstelsel moeten naast de 10 decimale cijfers nog 6 extra symbolen ingevoerd worden. Men gebruikt hiervoor de letters van a ( A ) tot en met f ( F ) = x6b =
44 Opgave. Schrijf een functie die een positief geheel getal omzet in binaire voorstelling. Schrijf een functie die de binaire voorstelling van een positief geheel getal omzet in decimale vorm. # d2b.py : decimaal naar binair def d2b(n) : l = [ ] while n > 0 : if n % 2 == 0 : l. append (0) else : l. append (1) n /= 2 l. reverse () return l De oproep d2b(75) heeft als resultaat een lijst: [1,0,0,1,0,1,1]. # b2d.py : decimaal naar binair def b2d( l ) : r = l [ 0 ] for i in range (1, len ( l ) ) : r = r 2 + l [ i ] return r De oproep b2d([1,0,0,1,0,1,1]) heeft als resultaat 75. Python heeft functies om een geheel getal om te zetten naar een binaire, octale of hexadecimale voorstelling: >>> a = 75 >>> print bin (a), oct (a ), hex(a) 0 b x4b Een overzicht van enkele getallen in de verschillende talstelsels: binair octaal decimaal hexadecimaal a b c d e f Probleem. Een bit kan maar twee mogelijke waarden hebben: 0 of 1. Hoe moet het minteken van een geheel getal of de komma van een reëel getal voorgesteld worden? 6.3 Gehele getallen Een geheel getal kan in twee bytes (16 bits) gestockeerd worden. Eén bit is voorbehouden als tekenbit. Het grootste positieve getal is dus =
45 getal voorstelling Negatieve gehele getallen worden voorgesteld in de twee-complement-vorm. De hoogste bit wordt gebruikt als tekenbit en stelt de kleinst mogelijke negatieve waarde voor. Wanneer 16 bits gebruikt worden is dit gelijk aan 2 15 = De waarde van de binaire voorstelling van een andere negatief getal wordt berekend door de absolute waarde van het 15 bits-getal bij op te tellen. getal voorstelling verklaring = = = = = = Een gemakkelijke methode om de 2-complement voorstelling te berekenen is de volgende: bepaal de binaire voorstelling van de absolute waarde van het getal; complementeer elke bit en tel bij dit complement 1 op; het resultaat is de 2-complement voorstelling. Een voorbeeld: de voorstelling van -2 binaire voorstelling van complement bijtellen resultaat Om de decimale waarde van een 2-complement voorstelling te berekenen, kan dezelfde methode gebruikt worden: 6.4 Reële getallen decimale voorstelling van complement bijtellen resultaat dus -15 Een reëel getal kan (benaderend) voorgesteld worden in een wetenschappelijke notatie in de vorm Het gedeelte voor het teken wordt mantisse (of significand) genoemd, daarna komt de basis gevolgd door de exponent. Normaal wordt als basis 10 gebruikt. In deze floating point vorm kan dus elk reëel getal geschreven worden met behulp van twee gehele getallen = en = en = en 3 45
46 Op deze manier kan een reëel getal dus op verschillende manieren voorgesteld worden. Om tot een uniforme manier te komen, bestaan er standaards. Tegenwoordig wordt de ANSI/IEEE norm gebruikt. Er wordt met een basis 2 gewerkt en door de mantisse te beperken tot het interval [1.0, 2.0[ is ook de exponent uniek gedefinieerd. S exponent (E) mantisse (M) of ( 1) S M 2 E bijv = ( 1) De mantisse M is steeds van de vorm 1.f en dus hoeft alleen het fractiegedeelte f gestockeerd te worden. Bijvoorbeeld 0.25 = Er worden slechts een beperkt aantal bytes voorzien om de mantisse en de exponent te stockeren. Met zo n eindige binaire string kan niet om het even welk decimaal getal exact voorgesteld worden. Meestal is in deze binaire string de eerste bit het teken van de mantisse, de volgende bits geven zowel de tekenbit als de waardebits van de exponent en de resterende bits zijn de waardebits van het fractiegedeelte (f) van de mantisse. Beide delen moeten ook negatieve getallen kunnen voorstellen. Voor de mantisse wordt met een tekenbit (S) gewerkt. Voor de exponent (met 8 bits) wordt echter gebruik gemaakt excess 127 mode. bit-patroon exponent verklaring Bij het type float worden 4 bytes voorzien: 1 tekenbit, 8 bits voor de exponent en 23 bits voor de fractie van de mantisse. De interne voorstelling van het reële getal 10.0 is dus: Een kortere schrijfwijze mbv. hexadecimale voorstelling: 0x Elementaire types Python kent de volgende elementaire types: int, float, complex, bool en str. Het type van een object kan opgevraagd worden met de functie type: >>> a = 4; type (a) <type int > >>> b = 3.0; type (b) <type f l o at > >>> c = appel ; type ( c ) <type str > >>> d = True ; type (d) <type bool > >>> z = j ; type ( z ) <type complex > 46
47 In tegenstelling tot vele andere programmeertalen zijn in Python complexe getallen beschikbaar waarop de klassieke operaties kunnen gebeuren. Met de attributen real en imag kan het reeël en imaginair deel opgevraagd worden. Met de functie complex met twee getallen als argumenten, kan een complex getal geconstrueerd worden. >>> a = j >>> a. real, a. imag (2.0, 3.0) >>> b = complex ( 1,4) >>> a+b (1+7 j ) >>> a b (3 1 j ) >>> a b ( 14+5j ) >>> a / b ( j ) >>> a 0.5 ( j ) Voor de types van numerieke waarden (int en float) wordt in geheugen een plaats met een vaste lengte voorzien, namelijk 8 bytes. Bij deze binaire voorstellingen wordt telkens één bit gebruikt als tekenbit. Het grootste positieve geheel getal dat kan voorgesteld worden is in binaire voorstelling 63 opeenvolgende eentjes of Wanneer bij dit getal 1 bijgeteld wordt, zou de hoogste bit op 1 komen, en zou er dus een negatieve waarde ontstaan. Python schakelt echter over naar waarden van type long: >>> L Waarden van dit type worden aangegeven door op het einde van het getal de letter L te plaatsen. 6.6 Nauwkeurigheid Gehele getallen. Met gehele getallen (int en aanverwanten) kan exact gerekend worden. Omdat slechts een beperkt aantal bytes voorzien worden om een geheel getal te stockeren kan er overflow of underflow optreden. tegroot = teklein = Overflow treedt op wanneer het getal te groot en positief is om het te stockeren in de variabele. In het bovenstaande voorbeeld zal de variabele tegroot niet de gespecificeerde waarde hebben. Analoog treedt underflow op wanneer het getal te groot en negatief is om het te stockeren in de variabele. Bij het rekenen met gehele getallen zou dus overflow ontstaan. De meeste programmeertalen signaleren dit niet maar de resultaten zijn fout! Op processor-niveau kan het via de overflow-vlag gecontroleerd worden. short a = ; short b = ; de som a + b : Zoals hoger al aangegeven is er in Python geen probleem. Bij een eventuele overflow wordt automatisch overgeschakeld naar type long. 47
48 Reële getallen. Aangezien de mantisse uit een beperkt aantal bits bestaat, zijn er ook slechts een beperkt aantal beduidende cijfers te stockeren. Dit impliceert eventueel verlies van nauwkeurigheid. Hoeveel bits voorzien worden voor exponent en mantisse is systeemafhankelijk. In klassieke systemen wordt het onderscheid gemaakt tussen enkelvoudige nauwkeurigheid en dubbele nauwkeurigheid. De beschikbare bytes worden als volgt verdeeld: enkelvoudig, waarde gebruikt 4 bytes: één byte wordt gebruikt voor de exponent en de overige drie voor de mantisse; met deze drie bytes kan men een nauwkeurigheid bereiken van 6 decimale cijfers; de exponent in basis 10 ligt in het interval [ 38, 38]; dubbel, waarde gebruikt 8 bytes: de 64 bits worden opgedeeld in 11 bits voor de exponent en de rest voor de mantisse; dit geeft een nauwkeurigheid van tenminste 15 decimale cijfers met een bereik voor de exponent (basis 10) gelijk aan [ 308, 308]. Python voorziet standaard het type float waarbij 8 bytes gebruikt worden, dus dubbele nauwkeurigheid. De ontwikkelaars van de numpy module hebben toch arrays voorzien waarbij de elementen in enkelvoudige nauwkeurigheid opgeslagen worden. Op het eerste zicht lijkt rekenen in enkelvoudige nauwkeurigheid meestal voldoende. Maar sommige numerieke berekeningen zijn inherent numeriek instabiel zodat zeer kleine fouten zeer snel kunnen groeien. Opgave. Schrijf een programma dat een vierkante matrix a genereert met a ij = 1/(i + j 1) voor 1 i n en 1 j n (dit is een Hilbert matrix van orde n). Laat het programma voor verschillende n waarden de determinant berekenen en afdrukken # determinant. py bereken determinant met a[i][ j] = 1/(i+j+1) 2 # (i en j starten bij rij 0 en kolom 0) import numpy 4 def hoegroot () : 6 invoer = raw input ( Geef grootte : ) n = int ( invoer ) 8 return n 10 def afdrukken (a, n) : for i in range (n) : 12 for j in range (n) : print 13.7 f % (a [ i ] [ j ] ), 14 print print 16 def genmatrix (x, n) : 18 for i in range (n) : for j in range (n) : 20 x [ i ] [ j ] = 1.0/( i+j +1.0) 22 def determinant(x, n) : EPS = 1.0E 8 24 wissel = 0 for i in range (n 1) : 26 rmax = i 48
49 for r in range ( i +1,n) : 28 if abs (x [ r ] [ i ] ) > abs (x [ rmax ] [ i ] ) : rmax = i 30 i f rmax > i : wissel += 1 32 for k in range ( i, n) : temp = x [ i ] [ k ] 34 x [ i ] [ k ] = x [ rmax ] [ k ] x [ rmax ] [ k ] = temp 36 for r in range ( i +1,n) : if abs (x [ i ] [ i ] ) > EPS : 38 faktor = x [ r ] [ i ]/ x [ i ] [ i ] else : 40 print PANIEK, n=, n, i=, i, r=, r exit () 42 for k in range ( i, n) : x [ r ] [ k ] = x [ r ] [ k ] faktor x [ i ] [ k ] 44 if wissel% 2 == 1 : det = else : det = for i in range (1,n) : det = x [ i ] [ i ] 50 return det 52 def main ( ) : m = hoegroot () 54 for n in range (2,m) : a = numpy. zeros ( [ n, n ], numpy. float32 ) 56 genmatrix (a, n) # afdrukken(a,n) 58 d = determinant (a, n) # afdrukken(a,n) 60 print n=, n, determinant i s, d # startoproep 62 main () Het resultaat voor verschillende n waarden wanneer met float32 (enkelvoudige precisie) en met float64 (dubbele precisie) gerekend wordt: n float32 float64 exact e e = e e e = e e e = e e e = e e e e e e e-33 Merk op dat in het programma slechts op één plaats een aanpassing moet gebeuren voor de berekening in enkelvoudige of dubbele precisie: a = numpy. zeros ( [ n, n ],numpy. float32 ) a = numpy. zeros ( [ n, n ],numpy. float64 ) 49
50 6.7 Type conversie Wanneer operandwaarden in een expressie van verschillend type zijn, dan worden deze operandwaarden naar een gemeenschappelijk type geconverteerd. operand 1 operand 2 gemeenschappelijk type str int niet mogelijk int long long int float float int complex complex float complex complex Er wordt dus telkens impliciet geconverteerd naar het grotere type. Daardoor zal zo weinig mogelijk informatie omwille van afkapping verloren gaan. Bij een toekenningsexpressie kan echter een conversie van een groter type naar een kleiner type nodig zijn. >>> i = 31 >>> f = 4.0 >>> res = int ( i / f ) # deling geeft 7.75 en bij de toekenning: 7 Bij de deling wordt de inhoud van de variabele i omgezet naar een float, dan wordt de deling uitgevoerd met als resultaat Dit float resultaat wordt nu omgezet naar een integer waarde door middel van de functie int. Dit gebeurt door afkappen, er is dus informatie verlies. Het resultaat wordt dan toegewezen aan de variabele res waarvan de waarde dus van type int is. Soms is het nodig expliciet een conversie op te leggen (in sommige programmeertalen spreekt men dan van casting). Dit kan door het oproepen van de gewenste type functie met als argument de waarde die moet geconverteerd worden. In volgend voorbeeld worden int waarden omgevormd naar float waarden. 1 # tcast. py: omzetten van types import numpy 3 def main ( ) : a = numpy. zeros ( [ 5 ], f l o a t ) 5 i = 3 j = 2 7 a [ 0 ] = i / j a [ 1 ] = float ( i )/ j 9 a [ 2 ] = i / f l o a t ( j ) print a 11 # startoproep main () Het resultaat van dit programma: [ ] 6.8 Begrippen Talstelsels. Interne voorstelling van gehele en reële getallen. Elementaire types. Conversie operaties: impliciet en expliciet. 50
51 7 Niet-numerieke data-types Een computer kan naast numerieke gegevens ook niet-numerieke informatie verwerken. Tot nu toe is dat alleen gebleken bij het print statement. Een mogelijk argument is een opeenvolging van letters tussen quotes ( ). 7.1 Interne voorstelling van tekens Een teken (of symbool, karakter) wordt gespecificeerd door middel van enkel quotes ( ): >>> c = a # c = a : dubbelzinnig >>> ord ( c ) 97 >>> chr (98) b Door de toekenning heeft de variabele c de teken-waarde van de letter a gekregen. Deze waarde kan omgezet worden naar een getal, met behulp van de functie ord. Omgekeerd, kan met behulp van de functie chr een getal (in het gepaste bereik) omgezet worden naar een letter. Aangezien computers oorspronkelijk nogal amerikaans getint waren en de amerikaanse taal slechts een beperkte verzameling van letters gebruikt (de 26 letters van het alfabet), is één byte in het werkgeheugen voldoende om een teken te stockeren. In één byte (acht bits) kunnen 2 8 = 256 mogelijke waarden gestopt worden. Dit is ruim voldoende voor alle letters van het alfabet en nog heel wat andere tekens. Intern wordt dus een teken voorgesteld als een rij van acht bits, bijvoorbeeld de letter a : x61 Bij interpretatie van de inhoud van een byte als een geheel getal, geldt natuurlijk dat de hoogste bit het teken van het getal aangeeft. Het interval van mogelijke waarden is dus [ 128, 127]. Oorspronkelijk werd beslist dat 127 tekens voldoende waren. Er werd een tabel opgesteld die voor elk teken de bijhorende numerieke waarde weergeeft en dus de interne (binaire) voorstelling definieert. Zoals gewoonlijk zijn er verschillende tabellen opgesteld geweest. Het meest gebruikte schema is ASCII (American Standard Code for Information Interchange). Op waarden van een teken variabele zijn geen rekenkundige operaties, zoals optelling en aftrekking, mogelijk, wel vergelijkingsoperatoren, zoals < en ==. Opgave. Maak een tabel met tekenwaarden en bijhorende hexadecimale codering. Laat de tabel beginnen met de waarde (spatie) en eindigen met ~. 1 # prascii. py: tabel met afdrukbare tekens import string 3 def main ( ) : print ASCII tabel 5 i = 32 while i < 127 : 7 print %1s %2x % ( chr ( i ), i ), if ( i+1)%8 == 0 : 9 print i += 1 11 print # startoproep 13 main () 51
52 Het resultaat: 20! 21 " 22 # 23 $ 24 % 25 & ( 28 ) 29 * 2a + 2b, 2c - 2d. 2e / 2f : 3a ; 3b < 3c = 3d > 3e? 40 A 41 B 42 C 43 D 44 E 45 F 46 G 47 H 48 I 49 J 4a K 4b L 4c M 4d N 4e O 4f P 50 Q 51 R 52 S 53 T 54 U 55 V 56 W 57 X 58 Y 59 Z 5a [ 5b \ 5c ] 5d ^ 5e _ 5f 60 a 61 b 62 c 63 d 64 e 65 f 66 g 67 h 68 i 69 j 6a k 6b l 6c m 6d n 6e o 6f p 70 q 71 r 72 s 73 t 74 u 75 v 76 w 77 x 78 y 79 z 7a { 7b 7c } 7d ~ 7e Merk op dat de codes voor de letters van het alfabet van klein naar groot gaan. Deze eigenschap van de ASCII tabel wordt gebruikt bij het sorteren van namen. Hoofdletters zijn alfabetisch kleiner dan kleine letters. De tabel start bij een numerieke waarde 0x20 of 32. De getallen tussen 0 en 31 worden gebruikt voor een aantal speciale tekens, die een specifieke betekenis binnen de informatica (+communicatie) wereld gekregen hebben. Een paar voorbeelden: hex-waarde dec-waarde Python-notatie betekenis 0 0 \0 het null teken 8 8 \b backspace 9 9 \t horizontal tab a 10 \n line feed, newline c 12 \f form feed d 13 \r carriage return Voor de Python-notatie wordt een \ gebruikt, gevolgd door een teken. Om het backslash teken zelf voor te stellen wordt \\ gebruikt. Analoog wordt de quote in Python genoteerd als \. Uit bovenstaande tabellen blijkt dat er een verschil is tussen de tekenwaarde 0 en het numeriek cijfer 0. De tekenwaarde 0 heeft een numerieke tegenwaarde gelijk aan 0x30. Opgave. Maak een tabel met symbool- of tekenwaarden van 0 tot 9 en bereken de bijhorende decimale cijferwaarde. 1 # c2d. py: omzetting van tekenwaarde naar cijferwaarde def main ( ) : 3 print l e t t e r code hex getal for c in [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ] : 5 i = ord ( c ) d = i ord ( 0 ) 7 print %6s %4d %3x %5d % (c, i, i, d) # startoproep 9 main () Opgave. Schrijf een programma dat een tekst symbool per symbool leest (niet stockeert) en het aantal symbolen telt alsook het aantal letters e of E in de tekst. De tekst wordt afgesloten met Ctrl-Z Enter. Ctrl-Z is het EOF (End Of File) symbool bij klassieke PC-besturingssystemen. 52
53 Hulp. Gebruik de methode read() van het object stdin uit de module sys: deze methode leest een aantal tekens van het toetsenbord, waarbij het gevraagde aantal tekens gespecificeerd wordt als argument; het resultaat van deze methode is de ingetikte string, eventueel één teken. Indien Ctrl-Z ingegeven wordt, dan geeft read de lege string als functiewaarde ( ) terug. 1 # symbtel. py: symbolen tellen import sys 3 def main ( ) : print geef een tekst, eindig met <ctrl > Z: 5 aantal tekens = 0 aantal e = 0 7 while True : teken = sys. stdin. read (1) 9 if not teken : break 11 if teken == e or teken == E : aantal e += 1 13 aantal tekens += 1 print Er z i jn %4d symbolen gelezen, % ( aantal tekens ) 15 print waarvan %4d \ e \ of \ E\ % ( aantal e ) 17 # startoproep main () Een methode is gelijkaardig aan een functie: het heeft argumenten en het geeft iets terug; alleen de syntax is wat anders. Er wordt gebruikt gemaakt van de dot notatie: object.methode(argumenten) Opgave. Schrijf een programma dat een tekst symbool per symbool leest (niet stockeert) en het aantal woorden telt. De tekst wordt afgesloten met het CTRL-Z teken. # woorden.py: tellen van aantal woorden in een tekst 2 import sys def main ( ) : 4 print geef een tekst, eindig met <ctrl > Z: woorden = 0 6 vorig = while True : 8 teken = sys. stdin. read (1) if not teken : 10 break if not teken. isalpha () and vorig. isalpha () : 12 woorden += 1 vorig = teken 14 if not teken and vorig. isalpha () : woorden += 1 16 print Het aantal woorden in de tekst i s, woorden 18 # startoproep main () 53
54 7.2 Strings Constanten Een string is een opeenvolging van tekens, bijvoorbeeld appel. Eventueel is het een opeenvolging van slechts één teken (bijv. x ). In Python wordt dus eigenlijk geen onderscheid gemaakt tussen tekens en strings. Beide waarden zijn van het type str Variabelen Om met strings bewerkingen uit te voeren, zijn variabelen nodig die geconstrueerd worden met behulp van een toekenning: >>> woord = sinaasappel >>> len (woord) 11 >>> woord [ 6 ] a >>> woord [ 3 : 6 ] aas >>> woord [ : 6 ] sinaas >>> woord [ 6 : ] appel De functie len berekent de lengte van zo n sequentie, in dit geval dus van de string. De verschillende tekens in de string kunnen aangesproken worden met een index i waarbij het eerste teken overeenkomt met index 0. Uit zo n string kunnen substrings geselecteerd worden (slicing): woord[i:j] selecteert alle letters uit de string met index k zodat i k < j. Wanneer de eerste of de tweede index weggelaten wordt, wordt de substring genomen respectievelijk vanaf het begin of tot op het einde van de string. Doorlopen van een string: Klassiek: i = 0 while i < len (woord) : l e t t e r = woord [ i ] print l e t t e r i += 1 Pythoniaans: for l e t t e r in woord : print l e t t e r Eens een string toegewezen is aan een variabele, kan deze niet meer gewijzigd worden. >>> woord [ 0 ] = S Traceback (most recent c a l l l ast ) : File <stdin>, l i n e 1, in <module> TypeError : str object does not support item assignment >>> woord = S + woord [ 1 : ] >>> woord Sinaasappel Wanneer de eerste letter toch een hoofdletter moet worden, kan dit door een nieuw object te creëren, in dit geval met de concatenatie operator (+) Bewerkingen Het optellingssymbool + plakt twee strings aan elkaar; het resultaat is een nieuwe string. Daarnaast heeft ook de vermenigvuldigingsoperator (*) een betekenis. 54
55 Vergelijkingsoperatoren kunnen op stringwaarden toegepast worden. Opgave. Lees een string van toetsenbord. Schrijf een functie die alle alfanumerieke tekens omzet naar hoofdletters. Schrijf de originele en de gewijzigde string uit. 1 # k2g. py: omzetting van kleine naar grote letters def doen ( geg ) : 3 v e r s c h i l = ord ( a ) ord ( A ) res = 5 for c in geg : if a <= c <= z : 7 i = ord ( c ) i = v e r s c h i l 9 res += chr ( i ) else : 11 res += c return res 13 def main ( ) : 15 geg = raw input ( woord in kleine l e t t e r s : ) res = doen ( geg ) 17 print geg, >, res 19 # startoproep main () Opgave. Lees twee strings van toetsenbord. Schrijf deze twee strings in alfabetische volgorde uit. # alfa2.py : alfabetisch afdrukken van twee strings 2 def main ( ) : naam1 = raw input ( tik een naam in : ) 4 naam2 = raw input ( tik een tweede naam in : ) vgl = naam1 == naam2 6 if vgl : print naam1, i s g e l i j k aan, naam2 8 elif naam1 < naam2 : print naam1, naam2 10 else : print naam2, naam1 12 # startoproep 14 main () Daarnaast kunnen op objecten van type string een heleboel methodes uitgevoerd worden: isalnum() alfanumeriek isprint() afdrukbaar-teken isalpha() alfabetisch isspace() spatie-teken isdigit() numeriek lower() omzetting naar kleine letter isupper() hoofdletter upper() omzetting naar hoofdletter islower() kleine letter find() index waarop meegegeven substring begint 55
56 Bovenstaand programma om een woord om te zetten naar hoofdletters kan dus korter met behulp van een voorgedefinieerde methode: >>> a = appel >>> b = sinaas >>> c = a. upper () >>> d = b. lower () >>> d+c sinaasappel >>> c 3 APPELAPPELAPPEL >>> d. find ( aas ) Lijsten van strings Opgave. Schrijf een programma dat een lijst van namen inleest en toevoegt aan een list, en daarna een naam inleest. De lijst wordt afgesloten met het EOF teken. Daarna wordt nagegaan of de extra ingelezen naam in de elementen van de lijst voorkomt. # linzoek.py: lineair zoeken in een lijst van namen 2 def l e e s l i j s t () : i = 0 4 l = [ ] while True : 6 try : w = raw input ( volgende naam: ) 8 l. append (w) i += 1 10 except EOFError : print 12 break return l 14 def zoek ( l i j s t, naam) : 16 for i in range ( len ( l i j s t ) ) : if naam == l i j s t [ i ] : 18 return i return 1 20 def main ( ) : 22 l i j s t = l e e s l i j s t () naam = raw input ( te zoeken naam: ) 24 res = zoek ( l i j s t, naam) if res >= 0 : 26 print naam, gevonden in, l i j s t, op plaats, res else : 28 print naam, niet gevonden in, l i j s t 30 # startoproep main () Merk op dat het zoeken in een lijst ook kan met de in operator: 56
57 def zoek ( l i j s t, naam) : if naam in l i j s t : return 1 return 1 Hiermee kan wel niet bepaald worden op welk plaats in de lijst de naam voorkomt. 7.4 Operaties met bits Een byte is het kleinste adresseerbare element in het werkgeheugen. Zo n element kan wel geinterpreteerd worden als een rij van 8 bits. In sommige toepassingen zijn manipulaties op deze kleinere elementen, de bits, nodig. In Python zijn hiervoor een aantal operatoren voorzien. Deze operatoren kunnen toegepast worden op waarden van het type int. Definitie van de verschillende operatoren: ~ bitsgewijze inversie of 1-complement & bitsgewijze en ^ bitsgewijze exclusieve of bitsgewijze inclusieve of << schuiven naar links >> schuiven naar rechts ~ & ^ Ook de corresponderende toekenningsoperatoren ( &=, ^=, =, <<= en >>= ) bestaan. # bitop. py : bitoperaties 2 def main ( ) : a = 0x01 4 b = 0x02 c = 0x03 6 print %2x > %2x % ( b, b ) print %2x & %2x > %2x % ( a, b, a&b ) 8 print %2x & %2x > %2x % ( a, c, a&c ) print %2x ˆ %2x > %2x % ( a, b, aˆb ) 10 print %2x ˆ %2x > %2x % ( a, c, aˆc ) print %2x %2x > %2x % ( a, b, a b ) 12 print %2x %2x > %2x % ( a, c, a c ) c = print %3d << 2 > %3d % ( c, c<<2 ) print %3d >> 2 > %3d % ( c, c>>2 ) 16 c = 120 print %4d >> 2 > %3d % ( c, c>>2 ) 18 l = G k = ord ( l ) 0x20 20 print %s > %s % ( l, chr (k) ) 22 # startoproep main () De resultaten: 57
58 ~ 2 -> -3 1 & 2 -> 0 1 & 3 -> << 2 -> ^ 2 -> >> 2 -> 30 1 ^ 3 -> >> 2 -> > 3 G -> g 1 3 -> 3 Bij de << worden de bits naar links geschoven; vooraan verdwijnen bits, achteraan worden nul-bits toegevoegd. Verschuiven naar links over n posities komt overeen met een vermenigvuldiging met 2 n. Bij de >> gebeurt het omgekeerde: er worden bits naar rechts geschoven en achteraan verdwijnen bits. Wat er vooraan toegevoegd wordt, is afhankelijk van het teken van de eerste operand (hoogste bit). Wanneer deze tekenbit gelijk is aan 0, worden nul-bits toegevoegd. Wanneer deze tekenbit gelijk is aan 1, worden één-bits toegevoegd. Dit noemt men sign-extension. Verschuiven naar rechts over n posities komt overeen met een deling door 2 n. 7.5 Begrippen Inwendige voorstelling van tekens, de ASCII tabel. Strings, stringfuncties, pointers naar strings. Bit operatoren: ~, &, ^,, <<, >>. Sign-extension. 58
59 8 Samengestelde datatypes 8.1 Sequenties en mappings In een vorig hoofdstuk werden arrays behandeld als een samengesteld data-type, namelijk een verzameling van een aantal waarden (elementen) die elk een zelfde type hebben. Gerelateerde waarden worden op die manier gegroepeerd in een samengesteld object. Dit vereenvoudigt het gebruiken van zo n reeks van waarden. Zo n array (mbv. de module numpy) is gebouwd met een basis Python constructie, een lijst, wat op zijn beurt een sequentie is. In vorig hoofdstuk werden strings gedefinieerd. Zo n string is ook een sequentie. Een ander soort samengesteld datatype is een mapping. Python heeft de dictionary als concrete implementatie van een mapping. Sequenties en mappings zijn beide onderdelen van het collection type. 8.2 Tuple Definitie Om waarden van verschillende types te kunnen groeperen, gebruikt men tuples. Een tuple is een samenhangende collectie waarden, die van verschillend type kunnen zijn. Een element uit een tuple wordt aangesproken met een index, zoals bij een string. De tuple in zijn geheel kan als variabele worden gebruikt. Een tuple definiëren gebeurt met een opsomming van waarden, gescheiden door komma s. Alhoewel het niet nodig is, worden deze waarden gewoonlijk tussen ronde haakjes geplaatst. >>> a = jos, 17, 54.4 >>> d = ( jos, 17, 54.4 ) >>> print a ( jos, 17, ) Maar bij het printen worden de haakjes wel weergegeven. Deze tuple bevat bijvoorbeeld informatie over een persoon: naam, leeftijd en gewicht. Merk op dat één waarde tussen haakjes geen tuple is. Om een tuple met één waarde te maken moet deze waarde gevolgd worden door een komma. Een lege tuple kan wel gemaakt worden met twee haakjes, zonder waarde er tussen. >>> e = () >>> s = (3) >>> t = (4,) >>> type ( e ), type ( s ), type ( t ) (<type tuple >, <type int >, <type tuple >) Er is ook een standaard functie tuple() die het argument omzet naar een tuple: >>> e = tuple () >>> w = appel >>> l = [1,2,3,4] >>> print e=, e e= () >>> print w=, tuple (w) w= ( a, p, p, e, l ) >>> print l=, tuple ( l ) l= (1, 2, 3, 4) 59
60 Wanneer het argument een sequentie is (string, lijst, tuple), is het resultaat een tuple bestaande uit de elementen van deze sequentie. Net zoals bij een string kan een individueel element of een reeks van opeenvolgende elementen aangesproken worden: >>> f = tuple ( sinaasappel ) >>> print f ( s, i, n, a, a, s, a, p, p, e, l ) >>> print 2e l e t t e r=, f [ 1 ], l a a tste letter, f [ 1] 2e l e t t e r= i l a a tste l e t t e r= l >>> print d e eltje=, f [ 5 : 8 ] d e e lt je= ( s, a, p ) >>> print eerste deel=, f [ : 6 ] eerste deel= ( s, i, n, a, a, s ) >>> print l a a tste deel=, f [ 6 : ] eerste deel= ( a, p, p, e, l ) Net zoals een string is een tuple niet-muteerbaar: >>> f = tuple ( sinaasappel ) >>> f [ 0 ] = S Traceback (most recent c a l l l ast ) : File <stdin>, l i n e 1, in <module> TypeError : tuple object does not support item assignment >>> f = ( S,) + f [ 1 : ] >>> print f ( S, i, n, a, a, s, a, p, p, e, l ) Maar je kan wel uit een tuplewaarde een nieuwe waarde berekenen en deze dan de naam van de oorspronkelijke tuple toewijzen. De waarde van de oorspronkelijke tuple is er dan nog wel, maar heeft geen naam meer; dat object is dus afval geworden. Een tuple kan zelf een element zijn van een andere tuple. Veronderstel dat we gegevens over een student wensen te bewerken: elementen zijn de persoonsgegevens en een lijst met behaalde scores: >>> p = ( jos, 21, 65.8) >>> s = ( p, [12, 14, 9, 16] ) >>> print s (( jos, 21, ), [12, 14, 9, 16]) >>> print s [ 0 ] [ 1 ], s [ 1 ] [ 1 ] De eerste index haalt over de overkoepelende tuple een element. Dit is op zijn beurt terug een tuple, waarin met de tweede index een element geselecteerd wordt. De samenstellende elementen hoeven niet van verschillende types te zijn. Wanneer men in een toepassing een reeks van constanten nodig heeft, waaruit op verschillende plaatsen in het programma de i de constante moet aangesproken worden, dan is een tuple de geschikte datastructuur. #dagop.py : dagen van de week 2 def main ( ) : dag = ( maandag, dinsdag, woensdag, donderdag, 4 vrijdag, zaterdag, zondag ) print De veilingdagen z i jn :, 6 for i in range (0, len (dag) 1,2) : print dag [ i ], 60
61 8 print print De tussendagen z i jn :, 10 for i in range (1, len (dag ),2) : print dag [ i ], 12 print # startoproep 14 main () Operaties De + operator plakt tuples aan elkaar (concatenatie). De * operator herhaalt een aantal concatenatie operaties. Met de in operator kan getest worden of een waarde een element is van de tuple. Vergelijking van tuples gebeurt element per element te beginnen bij het nulde element. Zolang overeenkomstige elementen gelijk zijn, wordt verder gegaan met het volgende element. Eens twee overeenkomstige elementen niet meer gelijk zijn, worden de overige elementen niet meer bekeken. >>> s = (1, 4, 100 ) >>> t = (1, 7, 30 ) >>> s+t (1, 4, 100, 1, 7, 30) >>> s 3 (1, 4, 100, 1, 4, 100, 1, 4, 100) >>> s < t True >>> s == t False >>> 100 in s True Bij de vergelijking, s < t, wordt het eerste element van s met dat van t vergeleken. Deze zijn gelijk, en dat wordt naar de tweede elementen van s en t gekeken. Er is aan de voorwaarde voldaan (4 < 7) en dus worden de volgende elementen niet meer bekeken Toekenning en terugkeerwaarde In een vorig hoofdstuk werd volgend statement geïntroduceerd a, b = 10, 99 Hiermee wordt in één statement twee objecten gemaakt en elk een naam gegeven. In feite is de linkerzijde een tuple van namen en de rechterzijde een tuple met expressies. Er gebeurt dus een tuple toekenning. Het aantal elementen in de tuple langs links moet wel gelijk zijn aan het aantal elementen in de tuple langs rechts. De rechterzijde kan om het even welke sequentie (string, lijst of tuple) zijn. Bijvoorbeeld, in een vorig hoofdstuk werd de split() methode op een waarde van type string vermeld. Wanneer geen argument gespecificeerd wordt, wordt de string gesplitst op basis van tussenliggende spaties. Er kan echter ook een argument meegegeven worden dat dan als scheidingsteken gebruikt wordt. Bijvoorbeeld het splitsen van een adres in gebruikersnaam en domein resulteert in een tuple met twee elementen: >>> = zeghetmij@rector. kuleuven. be >>> naam, domein = . s p l i t ) >>> print naam=, naam, domein=, domein naam= zeghetmij domein= rector. kuleuven. be 61
62 Bij het hoofdstuk over functies is aangegeven dat een functie meerdere terugkeerwaarden kan hebben. Eigenlijk wordt een tuple met meerdere elementen teruggegeven. Voorbeeld: bij gehele getallen zijn er twee operatoren / en % om respectievelijk het quotiënt en de rest te berekenen. Er bestaat een standaardfunctie (divmod) die deze twee resultaten tegelijk berekent: >>> q, r = divmod (11,3) >>> print quotient=, q, rest=, r quotient= 3 rest= 2 >>> t = divmod (11,3) >>> print type ( t ), quotient=, t [ 0 ], rest=, t [ 1 ] <type tuple > quotient= 3 rest= Named tuple Om de leesbaarheid van een programma met tuples te bevorderen, zou het aangewezen zijn om de verschillende elementen in een tuple een naam te geven. Om zo n element aan te spreken zou dan niet meer met een index, maar met een naam kunnen gewerkt worden. Python heeft een module collections met een methode om zo n named tuple te maken: import c o l l e c tions as co Mens = co. namedtuple( Mens, naam l e e f t i j d gewicht ) x = Mens( jos, 27, 64.5) Student = co. namedtuple ( Studerend, persoon, scores ) a = Student (x, [10, 14, 12, 9, 16]) print a. persoon.naam, met scores, for j in a. scores : print j, print Omdat de naam van de module nogal lang is, kan deze met de as constructie afgekort worden tot enkele letters. De functie om zo n named tuple te maken heeft twee argumenten. Het eerste argument geeft de naam van het nieuwe type. Het tweede argument somt de namen op van de verschillende elementen van de tuple: een string met daarin de elementnamen gescheiden door spaties of komma s. In plaats van een string kan ook een sequentie van strings gegeven worden. naam leeftijd gewicht naam,leeftijd,gewicht [ naam, leeftijd, gewicht ] Het resultaat van de functie is een constructor waarmee waarden van dit nieuwe type kunnen gemaakt worden. Voor de eenvoud zouden we dit resultaat kunnen toekennen aan een variabele die dezelfde naam heeft als het eerste argument. Voor het onderscheid tussen het nieuwe type (het argument) en de constructor (het resultaat) kunnen we beter twee verschillende namen gebruiken. Voor de duidelijkheid begint deze naam met een hoofdletter. In het voorbeeld worden twee named tuples gemaakt, waarbij een tuple onderdeel is van de andere tuple. De verschillende elementen van de tuple worden niet via een index aangesproken maar met de veldnaam Deze wordt via een punt aan de naam van de tuple gekoppeld. Opgave. Schrijf een programma dat de afstand berekent tussen punt (1.0,1.0) en een aantal punten waarvan het eerste punt ingelezen worden. De andere punten worden uit dit eerste punt afgeleid door telkens de x-coördinaat met 1.0 te verhogen en de y-coördinaat met 1.0 te verlagen. 1 #afstand.py : berekenen van de afstand tussen twee punten AANTAL = 3 3 from math import sqrt 62
63 import c o l l e c t i o n s as co 5 def main ( ) : Punt = co. namedtuple( Punt, x, y ) 7 c = Punt (1.0, 1.0) l i j n = raw input ( Geef coordinaten van een punt : ) 9 getallen = l i j n. s p l i t () p = Punt( f l o at ( getallen [ 0 ] ), f l o a t ( getallen [ 1 ] ) ) 11 for i in range (AANTAL) : afstand = sqrt ( ( c. x p. x) 2 + ( c. y p. y) 2 ) 13 print c, p, afstand, afstand p = p. replace (x=p. x+1.0,y=p. y 1.0) 15 # startoproep main () Met de _replace() methode kan een element uit een tuple aangepast worden, waarbij wel een nieuw object gemaakt wordt. Met gewone tuples zou de afstandsberekening als volgt gedaan worden: afstand = sqrt ( ( c [0] p [0]) 2 + ( c [1] p [1]) 2 ) Dit is minder leesbaar; er kan best bij vermeld worden dat in het nulde element de x-coördinaat zit en in het eerste element de y-coördinaat. Merk op dat deze index-notatie ook kan gebruikt worden bij named tuples. 8.3 Lijst Definitie Een lijst is een opeenvolging van waarden. Deze waarden kunnen van om het even welk type zijn. Een lijst creëren kan met een opsomming van waarden, gescheiden door komma s, tussen vierkante haakjes. >>> l = [10, 20, 30, 40, 50] >>> print l, l [ 2 ], [ 2] [10, 20, 30, 40, 50] >>> l [ 2 ] /= 10 >>> l [ 2] /= 5 >>> print l, l [ 2 ], l [ 1 : 4 ] [10, 20, 3, 8, 50] 3 [20, 3, 8] Een element uit een lijst aanspreken gebeurt zoals bij de andere sequenties: een index tussen vierkante haakjes: elke geheeltallige expressie kan gebruikt worden als een index; een indexwaarde die overeenkomt met een niet-bestaand element, geeft een IndexError fout; een negatieve indexwaarde telt terug vanaf het einde van de lijst. Ook een reeks van opeenvolgende elementen kan aangesproken worden met de slice operator (:). In tegenstelling tot strings en tuples is een lijst muteerbaar: individuele elementen van een lijst kunnen een andere waarde krijgen. De waarden van de verschillende elementen van een lijst hoeven niet van hetzelfde type te zijn. In volgend voorbeeld is het eerste element een string, het tweede element een integer en het derde element is op zich een lijst. In het geval dat een element zelf een lijst is, spreekt men van een geneste lijst. Twee vierkante haakjes zonder waarde er tussen, creëert een lege lijst. >>> leeg = [ ] 63
64 >>> x = [ jan, 24, [2,3,5,7] ] >>> print leeg, x [ ] [ jan, 24, [2, 3, 5, 7 ] ] Operaties en bewerkingen De + operator plakt lijsten aan elkaar (concatenatie). De * operator herhaalt een aantal concatenatie operaties. Met de in operator kan getest worden of een waarde een element is van de lijst. >>> v = [ 1, 2, 3 ] >>> w = [ 4, 5, 6 ] >>> s = v+w >>> t = v 4 >>> print s=, s s= [1, 2, 3, 4, 5, 6] >>> print t=, t t= [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3] >>> 4 in s, 4 in t (True, False ) Daarnaast kan deze in operator gebruikt worden om een lijst te doorlopen: >>> x = [ jan, 24, [2,3,5,7] ] >>> for e in x :... print e... jan 24 [2, 3, 5, 7] Alhoewel het derde onderdeel van de lijst een lijst op zich is, wordt deze toch als één element behandeld door de in operator. Wanneer zo n for lus over een lege lijst loopt, worden de lus statements niet uitgevoerd. Er zijn verschillende methodes beschikbaar om bewerkingen op lijsten uit te voeren: append extend insert sort pop index remove achteraan toevoegen van één element achteraan uitbreiden met een lijst op aangegeven plaats een element toevoegen een lijst sorteren van klein naar groot een element via zijn index uit de lijst halen en ook verwijderen index van een element opvragen een element via zijn waarde uit de lijst verwijderen Daarnaast is er de del operator waarmee één element (mbv. een index) of meerdere opeenvolgende elementen (mbv. de slice operator) uit de lijst kan verwijderd worden. >>> v = [ 9, 7, 5, 3] >>> w = [ 2, 6, 8] >>> w. append (4) >>> print w [2, 6, 8, 4] >>> v. extend (w) >>> print v 64
65 [9, 7, 5, 3, 2, 6, 8, 4] >>> v. sort () >>> print v [2, 3, 4, 5, 6, 7, 8, 9] >>> print v. pop (2), v 4 [2, 3, 5, 6, 7, 8, 9] >>> del v [ 3 ] >>> print v [2, 3, 5, 7, 8, 9] >>> del v [ 2 : 4 ] >>> print v [2, 3, 8, 9] >>> v. i n s e r t (2, 99), v, v. index (99) (None, [2, 3, 99, 8, 9], 2) >>> v. remove (8) >>> print v [2, 3, 99, 9] In tegenstelling tot string-methodes geven de meeste lijst-methodes niets terug Als men toch probeert een teruggeefwaarde af te drukken, krijgt met None. Door de methode uit te voeren wordt de lijst zelf aangepast Lijsten en strings Een string is een sequentie van tekens (characters) en een lijst is een sequentie van waarden. Met de functie list() kan een string omgezet worden in een lijst van tekens. >>> a = appel >>> c = l i s t (a) >>> print a, >, c appel > [ a, p, p, e, l ] Om een string op te splitsen in woorden, kunnen we de split() methode gebruiken. Een optioneel argument geeft het scheidingsteken aan. >>> v = appelen en peren >>> print v. s p l i t () [ appelen, en, peren ] >>> print v. s p l i t ( e ) [ app, l, n, n p, r, n ] Met de join() methode wordt het omgekeerde gerealiseerd: een lijst van woorden wordt omgevormd naar een string met het aangegeven scheidingsteken: >>> f = [ appelen, en, peren ] >>> s = >>> t = s. join ( f ) >>> print f, >, t [ appelen, en, peren ] > appelen en peren 8.4 Objecten en waarden Door middel van de toekenningen 65
66 >>> a = appel >>> b = appel >>> a == b True worden aan twee waarden een naam gegeven. Aangezien deze twee waarden gelijk zijn, geeft de == operator het resultaat True. Maar dit wil niet zeggen dat de twee namen naar hetzelfde object verwijzen. Om dit na te gaan kan de is operator gebruikt worden. >>> a is b True In dit geval verwijzen de twee namen naar hetzelfde object. Wanneer uit deze strings lijsten gecreëerd worden, dan blijken deze wel dezelfde inhoud te hebben, maar niet naar hetzelfde object te verwijzen: >>> c = l i s t (a) >>> d = l i s t (b) >>> c == d True >>> c is d False Tot nu werden de termen object en waarde wat door elkaar gebruikt. Het is juister om te zeggen dat een object een waarde heeft. Daarnaast heeft elk object een type en ook een unieke identity. Zowel het type als de identiteit kan niet gewijzigd worden. Het type van een object kan opgevraagd worden met de type() functie. De id() functie heeft als resultaat een geheel getal dat deze identiteit voorstelt. Wanneer twee objecten dezelfde waarde hebben, worden deze twee objecten equivalent genoemd (te testen met ==). Het is mogelijk dat twee verschillende namen toch naar hetzelfde object verwijzen. Men spreekt dan van identieke objecten (te testen met is). Bij een toekenning b=a waarbij a de naam van een object is, zal b naar hetzelfde object verwijzen. >>> a = appel >>> b = a >>> a is b True Het object met waarde appel heeft nu twee namen (of referenties); men spreekt ook van een alias. Indien het hierbij gaat over muteerbare objecten (bijv. een lijst), dan gaat een wijziging via de ene alias, ook zichtbaar zijn via de andere alias: het gaat immers over hetzelfde object. >>> c = l i s t (a) >>> d = c >>> e = c [ : ] >>> d [ 1 ] = X >>> print c=, c, e=, e c= [ a, X, p, e, l ] e= [ a, p, p, e, l ] Meestal leidt dit effect tot fouten. Men kan beter aliassen van muteerbare objecten vermijden. Wanneer een lijst volledig moet gecopieerd worden en deze copie moet een nieuwe naam krijgen dan kan dat met de slice operator. Omdat er geen grenzen opgegeven zijn, worden de defaults gebruikt, d.i. het begin en het einde van de lijst. 66
67 Nochtans wordt bij een oproep van een functie voor elk argument in de formele parameter een alias gecreëerd. Zowel de naam van het argument als de naam van de parameter zijn referenties naar hetzelfde object. # argseq. py: sequenties als argument 2 def w i jziggetal (g) : print o r i g i n e e l getal :, g, id (g) 4 g = 27 print gewijzigd :, g, id (g) 6 return def w i jzigstring ( s ) : 8 print o r i g i n e l e string :, s, id ( s ) s = peer 10 print gewijzigd :, s, id ( s ) return 12 def wijzigtuple ( t ) : print o r i g i n e e l tuple :, t, id ( t ) 14 t = ( p, e, e, r ) print gewijzigd :, t, id ( t ) 16 return def w i j z i g l i j s t ( l ) : 18 print o r i g i n e l e l i j s t :, l, id ( l ) l [ 0 ], l [ 1 ], l [ 2 ], l [ 3 ] = p, e, e, r 20 del ( l [ 4 ] ) print gewijzigd :, l, id ( l ) 22 return 24 def main ( ) : a = 4 26 b = appel c = tuple (b) 28 d = l i s t (b) print id (a ), id (b), id ( c ), id (d) 30 w i jziggetal (a) print hoofdprogramma : getal, a, id (a) 32 w i jzigstring (b) print hoofdprogramma : string, b, id (b) 34 wijzigtuple ( c ) print hoofdprogramma : tuple, c, id ( c ) 36 w i j z i g l i j s t (d) print hoofdprogramma : l i j s t, d, id (d) 38 # startoproep 40 main () Aangezien strings en tuples niet-muteerbare objecten zijn, creëren de toekenningen in de functie een nieuw object. Maar eens terug in het hoofdprgramma refereert de naam nog altijd naar het oorspronkelijk object. Een lijst is echter een muteerbaar object. In de functie kan via de parameternaam een aanpassing aangebracht worden aan het object dat als argument meegegeven wordt. De uitvoer van het programma is origineel getal:
68 gewijzigd: hoofdprogramma: getal originele string: appel gewijzigd: peer hoofdprogramma: string appel origineel tuple: ( a, p, p, e, l ) gewijzigd: ( p, e, e, r ) hoofdprogramma: tuple ( a, p, p, e, l ) originele lijst: [ a, p, p, e, l ] gewijzigd: [ p, e, e, r ] hoofdprogramma: lijst [ p, e, e, r ] Lijsten en tuples Elementen uit verschillende sequenties, bijv. tuples, kunnen aan elkaar gerijgd worden mbv. de zip() functie: >>> f = ( appel, peer, citroen ) >>> k = ( rood, groen, geel ) >>> a = ( 3, 2, 4 ) >>> zip (a, k, f ) [(3, rood, appel ), (2, groen, peer ), (4, geel, citroen ) ] Het resultaat is een lijst van tuples waarbij elk tuple gevormd worden uit elementen van de verschillende input sequenties. Wanneer de lengte van de verschillende sequenties verschillend is, dan is het resultaat een lijst met de lengte afkomstig van de kortste sequentie. >>> f l = [ appel, peer, citroen, kiwi, banaan ] >>> kl = [ rood, groen, geel ] >>> zip ( kl, f l ) [ ( rood, appel ), ( groen, peer ), ( geel, citroen ) ] Meerdere sequenties tegelijk doorlopen kan door for, zip() en tuple-toekenning te combineren. Bijvoorbeeld, de volgende functie gaat na of er een index i bestaat waarbij in de twee sequenties dezelfde waarde staat. # match.py : nagaan of op een bepaalde plaats elementen gelijk zijn 2 def match( t1, t2 ) : for x, y in zip ( t1, t2 ) : 4 if x == y : return True 6 return False def main ( ) : 8 print match ([2,4,8,16], [3,5,8,13]) print match ([1,4,8,16], [2,3,5,8]) 10 # startoproep main () Het resultaat van de eerste oproep is True, omdat 8 in de twee lijsten op dezelfde plaats voorkomt. Het resultaat van de tweede oproep is False. Opgave. Schrijf een programma dat een reeks van woorden sorteert op basis van de woordlengte: van langste naar kortste, bij gelijke lengte wordt omgekeerd alfabetisch gewerkt. 68
69 1 # lensort. py : sorteren volgens woordlengte def lensort ( woorden) : 3 t = [ ] for w in woorden : 5 t. append ( ( len (w), w) ) t. sort ( reverse=true) 7 res = [ ] for l, w in t : 9 res. append (w) return res 11 def main ( ) : x = [ appel, peer, citroen, sinaasappel, kiwi, pruim ] 13 r = lensort (x) print r 15 # startoproep main () De methode sort() toegepast op een lijst van tuples, vergelijkt op basis van het eerste element van elk tuple. Wanneer deze gelijk zijn, wordt het tweede element gebruikt, enz. Het argument reverse=true zorgt er voor dat er van groot naar klein gesorteerd wordt. Het resultaat is [ sinaasappel, citroen, pruim, appel, peer, kiwi ] 8.6 Dictionary Definitie Een dictionary is een mapping tussen een verzameling sleutels en een verzameling waarden. In tegenstelling tot een lijst is een dictionary een ongeordende verzameling: elementen worden niet via een volgnummer (index) aangesproken, maar via een sleutel. Creatie kan gebeuren door een opsomming van sleutel-waarde paren tussen akkolades: >>> vakken = { algebra : De Samblanx, fysica : Langie, chemie : Dewil } >>> type ( vakken ) <type dict > >>> print vakken { chemie : Dewil, fysica : Langie, algebra : De Samblanx } >>> len ( vakken ) 3 De naam van een type is dus dict; deze naam kan ook gebruikt worden als functie om een lege dictionary te maken. Met de len functie kan de lengte opgevraagd worden. Zoals het print statement laat zien, ligt de volgorde van de paren niet vast: de volgorde bij uitvoer is anders dan bij creatie. Maar dat is geen probleem, omdat de elementen nooit via een volgnummer aangesproken worden, maar steeds via een sleutel: >>> print vakken [ fysica ] Langie >>> print vakken [ mechanica ] Traceback (most recent c a l l l ast ) : File <stdin>, l i n e 1, in <module> KeyError : mechanica 69
70 Wanneer een niet-bestaande sleutel gebruikt wordt, wordt een fout gegenereerd. Met de in operator kan getest worden of iets een sleutel is in de dictionary. Een sleutel met bijhorende waarde toevoegen aan een bestaande dictionary kan met een toekenning. >>> m = mechanica >>> m in vakken False >>> vakken [m] = Verheyden Opgave. Schrijf een functie met als argument een tekst, die voor elke voorkomende letter in de tekst telt hoe dikwijls de letter voorkomt. Een aantal mogelijke oplossingen: Creëer 26 variabelen, eentje voor elke letter. Doorloop de tekst en verhoog voor elke letter de corresponderende variabele met 1, met behulp van een if... elif... elif... else constructie. Creëer een lijst met 26 elementen. Converteer elke letter uit de tekst naar een getal (mbv. de ord functie) en gebruik dit getal als index in de lijst om de gepaste teller te verhogen. Creëer een dictionary met de letters als sleutels en de tellers als corresponderende waarden. Bij het eerste voorkomen van een letter wordt een item toegevoegd aan de dictionary; bij volgende voorkomens wordt de corresponderende waarde verhoogd met 1. # histogram. py: frequentie van letters in een tekst 2 def histogram( tekst ) : t e l l i n g = dict () 4 for c in tekst : if c not in t e l l i n g : 6 t e l l i n g [ c ] = 1 else : 8 t e l l i n g [ c ] += 1 return t e l l i n g 10 def main ( ) : tekst = raw input ( Geef een tekst : ) 12 t e l = histogram ( tekst ) print t e l 14 # startoproep main () Bij een invoer van woorden zonder zin is het resultaat: { : 2, e : 2, d : 2, i : 1, o : 3, n : 3, r : 2, w : 1, z : 2} Merk op dat de volgorde waarin de verschillende letters in de dictionary opgenomen zijn, willekeurig zijn Bewerkingen en methodes Twee dictionaries bij elkaar optellen of een dictionary met een geheel getal vermenigvuldigen is NIET mogelijk. De in operator kan in een for gebruikt worden om de verschillende sleutels in een dictionary te doorlopen. Met de keys() methode kan uit een dictionary een lijst met sleutels gegenereerd worden. Met de values() methode kan uit een dictionary een lijst van waarden gegenereerd worden. Met deze functies kan het histogram van letterfrequenties in alfabetische volgorde weergegeven worden: 70
71 tekst = raw input ( Geef een tekst : ) 2 te l = histogram( tekst ) l e t t e r s = t e l. keys () 4 l e t t e r s. sort () for s in l e t t e r s : 6 print s, :, t e l [ s ] Een tabel maken met oplopende frequenties en bijhorende letters is wat moeilijker. Er is een bijkomende functie nodig om voor een gegeven waarde (i.e. frequentie) de bijhorende sleutel (letter) te zoeken: def reverse zoek ( geteld, waarde) : 2 for l e t in geteld : if geteld [ l e t ] == waarde : 4 return l e t return None Wanneer er verschillende letters met dezelfde frequentie in de dictionary aanwezig zijn, vindt deze functie steeds dezelfde letter. Om de verschillende letters te vinden die bij een specifieke frequentie horen, wordt telkens een letter getoond is, dit letter-frequentie paar uit de dictionary verwijderd met het del statement. tekst = raw input ( Geef een tekst : ) 2 te l = histogram( tekst ) freqn = t e l. values () 4 freqn. sort () for fr in freqn : 6 l e t = reverse zoek ( tel, fr ) if l e t : 8 print fr, :, l e t del tel [ l e t ] Het resultaat is dat na uitvoer van dit gedeelte van het programma, de dictionary terug leeg is. Daarom is het misschien interessanter om uit de dictionary de omgekeerde dictionary te genereren. Hierin zijn de frequenties de sleutels. Bij elke sleutel is de waarde een lijst van letters die met die frequentie voorkomen in de gegeven tekst. 1 def rev histogram ( t e l l i n g ) : inverse = dict () 3 for l e t t e r in t e l l i n g : fre = t e l l i n g [ l e t t e r ] 5 if fre not in inverse : inverse [ fre ] = [ l e t t e r ] 7 else : inverse [ fre ]. append ( l e t t e r ) 9 return inverse # lijst met 1 element 11 # hoofdprogramma tekst = raw input ( Geef een tekst : ) 13 te l = histogram( tekst ) revtel = rev histogram ( tel ) 15 freqn = revtel. keys () freqn. sort () 71
72 17 for fr in freqn : print fr, :, revtel [ fr ] Bij een invoer van woorden zonder zin is het resultaat: 1 : [ i, w ] 2 : [, e, d, r, z ] 3 : [ o, n ] Dictionaries en tuples Met de methode items kan uit een dictionary een lijst van tuples gegenereerd worden waarbij elk tuple een sleutel-waarde paar is. Omgekeerd, een lijst van tuples kan gebruikt worden om een nieuwe dictionary te initaliseren. >>> t = [ ( rood, appel ), ( groen, peer ), ( geel, citroen ) ] >>> d = dict ( t ) >>> d. items () [ ( groen, peer ), ( rood, appel ), ( geel, citroen ) ] Met de update methode kan een lijst van tuples (als sleutel-waarde paren) toegevoegd worden aan een dictionary. >>> s = [ ( purper, paprika ), ( roos, tomaat ) ] >>> d. update ( s ) >>> d { purper : paprika, groen : peer, roos : tomaat, rood : appel, geel : citroen } Met de zip functie kan een dictionary op een compacte manier gecreëerd worden. >>> d = dict ( zip ( abcdef, range (5) ) ) >>> d { a : 0, c : 2, b : 1, e : 4, d : 3} De sleutel in een dictionary moet immutable zijn. Naast een string kan dus ook een tuple als sleutel in een dictionary gebruikt worden. Dit kan bijvoorbeeld gebruikt worden bij een dictionary met telefoonnummers waarbij de sleutel uit naam en voornaam bestaat. telefoon = dict () telefoon [ ( De Nayer, Jan ) ] = telefoon [ ( Ku, Leuven ) ] = Begrippen Samengestelde types: sequence: tuple en list. De selectie-operatoren: [] en [ : ]. Bewerkingen op tuples en lijsten. Object: waarde, type en identiteit. Samengesteld type: mapping: dictionary. 72
73 9 Persistentie via bestanden 9.1 Inleiding De programma s in de voorbeelden in de vorige hoofdstukken zijn transient. Zo n programma vraagt wat invoer aan de gebruiker, doet wat berekeningen en schrijft de resultaten uit op het scherm. Bij het einde van het programma verdwijnt alle data. Om het resultaat nog eens te berekenen, moet het programma terug uitgevoerd worden. In veel toepassingen is het gewenst om de resultaten van een programma te bewaren op een meer persistente manier. Dit kan door deze resultaten te bewaren op permanent geheugen bijvoorbeeld op een disk. Daarna kunnen deze resultaten dan terug gelezen worden om hiermee verder te werken in andere programma s. Een eenvoudige manier voor programma s om gegevens tussen twee runs te bewaren is het lezen en schrijven van tekstbestanden. Tekstbestanden zijn bestanden met daarin lijnen met tekst. Met bijvoorbeeld een tekst editor is zo n bestand te lezen en aan te passen door een menselijke gebruiker. 9.2 Bestanden Een bestand is een opslagplaats op een permanent geheugen, bijvoorbeeld een disk. Deze opslagplaats heeft een naam. Om zo n bestand in een Python programma te gebruiken (lezen of schrijven), heeft Python een built-in object type. Dit object bevat allerlei administratieve gegevens omtrent het bestand dat gebruikt wordt. Hierin zit o.a. waar ergens op de disk de data van het bestand kan gevonden worden. De inhoud van het bestand zelf is ergens op een extern medium (bijv. disk) gelokaliseerd maar om in- of uitvoer naar het bestand te doen, moeten deze administratieve gegevens snel toegankelijk zijn en moeten deze dus in het werkgeheugen aanwezig zijn. file object file fin... werkgeheugen disk Om in dit file object de verschillende elementen te initialiseren met de administratieve gegevens van het bestand waarop in- of uitvoer gedaan gaat worden, moet het bestand geopend worden. Dit gebeurt met de built-in functie open. Wanneer het lezen van of het schrijven naar het bestand afgelopen is, kan het file object terug opgeruimd worden door het bestand te sluiten mbv de methode close. fin = open ( appel. txt, r ) fin. close () De functie open heeft twee argumenten. Het eerste argument, naam, specificeert welk bestand van disk moet geopend worden. Dit gebeurt met behulp van de naam van het bestand zoals die op de disk gekend is. Wanneer het om een nieuw te creëren bestand gaat, duidt dit argument de naam aan, die vanaf dan kan gebruikt worden om het bestand te benoemen. Het tweede argument, mode, geeft aan hoe het bestand moet geopend worden. Er zijn verschillende mogelijkheden: r ( r+ ) w ( w+ ) a ( a+ ) lezen van bestaand bestand (ook schrijven kan) schrijven op nieuw bestand, dus creatie van bestand (ook lezen is mogelijk) achteraan toevoegen aan bestaand bestand (ook lezen is mogelijk) De return-waarde van open is een object met daarin voldoende administratieve gegevens om van het bestand te lezen en/of naar het bestand te schrijven. Tijdens het openen kan er een fout optreden. Het programma genereert dan een IOError en stopt ermee. 73
74 9.3 Lezen en schrijven van strings Wanneer een tekstbestand succesvol geopend is om er van te lezen, bijv. met de r mode, heeft Python een aantal methodes ter beschikking om de lees operatie uit te voeren. read() het lezen van het volledige bestand in één string read(n) het lezen van het n tekens (met n 1) readline() het lezen van de volgende lijn (inclusief eindlijn teken) readlines() het lezen van het volledige bestand in een lijst van strings Wanneer een tekstbestand succesvol gecreëerd is, met de w mode, heeft Python een aantal methodes om strings naar dit bestand weg te schrijven. write(s) writelines(l) schrijven van de string s naar het bestand schrijven van alle lijnstrings van een lijst l naar het bestand Voorbeeld: de inhoud van een bestand copiëren naar een ander bestand, lijn per lijn. # cplijn.py : copieert een bestand lijn per lijn 2 def main ( ) : fin = open ( l i j n. py, r ) 4 f u i t = open( weg. txt, w ) while True : 6 l i j n=fin. readline () if not l i j n : 8 break fuit. write ( l i j n ) 10 fin. close () f u i t. close () 12 # startoproep 14 main () In dit voorbeeld wordt het invoerbestand sequentieel gelezen en wordt op het uitvoerbestand sequentieel geschreven. Soms is het aangewezen om deze sequentiële volgorde te wijzigen. Dit kan met de seek() methode met twee argumenten: de offset en de referentie. De nieuwe positie in het bestand wordt berekend door de offset op te tellen bij het referentiepunt. Indien referentie gelijk is aan 0, is dit punt het begin van het bestand (absolute positionering). Indien referentie gelijk is aan 1, is dit punt de actuele positie in het bestand (relatieve positionering). Indien referentie gelijk is aan 2, is dit punt het einde van het bestand. De tell() methode geeft een geheel getal terug dat de actuele positie in een bestand vanaf het begin aangeeft, uitgedrukt in bytes. Voorbeeld: de inhoud van een bestand teken per teken in omgekeerde volgorde schrijven in een ander bestand. # revteken.py : copieert een bestand teken per teken 2 # in omgekeerde volgorde def main ( ) : 4 fin = open ( in. txt, r ) ; f u i t = open( uit. txt, w ) ; 6 fin. seek (0,2) # achteraan grootte = fin. t e l l () 8 aantal = 0 while aantal < grootte : # lengte bestand 10 fin. seek ( 1,1) # een positie terug teken=fin. read (1) # een positie vooruit 74
75 12 fuit. write ( teken ) print aantal, fin. t e l l () 14 fin. seek ( 1,1) # een positie terug aantal += 1 16 fin. close () f u i t. close () 18 # startoproep 20 main () 9.4 Opvangen van excepties Bij het openen van een bestand kan er wel wat misgaan: >>> fin = open( bestaatniet, r ) IOError : [ Errno 2] No such f i l e or directory : bestaatniet >>> fin = open( / etc, r ) IOError : [ Errno 21] Is a directory : / etc >>> fin = open( / etc /passwd, w ) IOError : [ Errno 13] Permission denied : / etc /passwd Om deze foutmeldingen te vermijden kan voor de open een test gebeuren of het bestand wel bestaat, of het wel een tekstbestand is, of het een bestand is dat mag aangepast worden,... Het is veel overzichterlijker om de actie gewoon te proberen en indien het misloopt, deze uitzondering op te vangen. Dit kan met het try statement (een beetje te vergelijken met het if statement). try : fin = open( bestaatniet, r ) for l i j n in fin : print l i j n fin. close () except : print er i s i e t s mis met het openen of lezen van het bestand Python start met het uitvoeren van de statemens in het try blok. Als alles goed verloopt, wordt het except blok overgeslagen. Wanneer echter een probleem optreedt, wordt uit het try blok gesprongen en wordt het except blok uitgevoerd. 9.5 Lezen en schrijven van andere waarden Met de hierboven vermelde functies kunnen strings gelezen en geschreven worden. Bij invoer van getallen kan de ingelezen lijn gesplitst worden met behulp van de split() methode. De elementen in de resulterende lijst kunnen dan één voor één omgezet worden naar int en float waarden. Wanneer het resultaat dat weggeschreven wordt, getallen (integer, float,...) bevat, moeten deze omgezet worden naar strings. Dit kan met de str() functie of met de format operator %. Deze operator heeft twee operands: de format string en een tuple met de variabelen die naar het bestand moeten geschreven worden. De formaat string bevat twee soorten objecten: gewone af te drukken tekens en format sequences. Elk van de waarden in de tuple worden omgevormd naar een string overeenkomstig de format sequence. Zo n format sequence begint met een % en eindigt op een conversieteken. 75
76 conversieteken corresponderende tuple element wordt omgevormd tot %d een geheel getal in decimale notatie %o een geheel getal in octale notatie %x een geheel getal in hexidecimale notatie %f een reëel getal in vaste komma notatie %e een reëel getal in drijvende komma notatie %g e of f conversie, de kortste vorm %s een string Tussen % en het conversieteken kan staan: - links in de beschikbare ruimte getal de veldbreedte. scheiding tussen veldbreedte en precisie getal de precisie - getal: het aantal cijfers rechts van het punt - string: het aantal afgedrukte tekens Wanneer na de % een teken volgt dat niet in bovenstaande lijsten opgenomen is, wordt dat teken gewoon afgedrukt. Dit is handig om het procent-teken zelf af te drukken, door middel van %%. Om het quote ( ) teken af te drukken, moet dit teken in de formaatstring voorafgegaan worden door een backslash: \. Voorbeeld: %10d 3456 %20.10f %10o 6600 %20.10e e+02 %10x d80 %20.10g %-10d 3456 %-20.10f # rwgetallen. py : getallen lezen van en schrijven naar een bestand 2 def main ( ) : t e l = 0 4 fin = open ( inweg. txt, r ) f u i t = open( uitweg. txt, w ) 6 while True : l i j n = fin. readline () 8 if not l i j n : break 10 drie = l i j n. s p l i t () i = int ( drie [ 0 ] ) 12 x = f l o a t ( drie [ 1 ] ) y = f l o a t ( drie [ 2 ] ) 14 voor = %3d : %5d %10.4 f %10.4 f % ( tel, i, x, y) print voor 16 achter = (0x%2x 0%4o %10.3e %g)\n % ( i, i, y x, x+y) fuit. write ( voor+achter ) 18 t e l += 1 fin. close () 20 f u i t. close () 22 # startoproep main () 76
77 9.6 Programma met argumenten Een programma bestaat uit een aantal functies en een hoofdprogramma. Bij het starten van het programma kunnen aan dit hoofprogramma een willekeurig aantal argumenten gegeven worden: python hfdarg.py appel peer genoeg 1 # hfdarg. py : programmaparameters import sys 3 def main ( ) : print aantal argumenten, len ( sys. argv ) 5 for i in range ( len ( sys. argv ) ) : print argv[%d ] = %s % ( i, sys. argv [ i ] ) 7 # startoproep main () Tijdens het starten van het programma, heeft het systeem ervoor gezorgd dat er actuele argumenten gemaakt worden voor het hoofdprogramma. Deze argumenten zijn in het programma beschikbaar in de lijst argv uit de sys module. Deze lijst bevat strings overeenkomend met de verschillende woorden die na python ingetikt zijn. Dus argv[0] bevat een string met waarde de naam van het programma; argv[1] bevat het eerste argument,... ; het laatste argument zit in argv[ len(sys.argv)-1 ]. argv[0] = hfdarg.py argv[1] = appel De uitvoer is dan argv[2] = peer argv[3] = genoeg Illustratie van de append mode: de inhoud van een aantal bestanden worden gecopieerd naar één bestand. # mcopie. py : resultaatfile infile1 infile2 infile import sys def main ( ) : 4 for i in range (2, len ( sys. argv ) ) : try : 6 fin = open( sys. argv [ i ], r ) # invoerbestand f u i t = open( sys. argv [ 1 ], a ) # uitvoerbestand 8 while True : l i j n=fin. readline () 10 if not l i j n : break 12 f u i t. write ( l i j n ) fin. close () 14 f u i t. close () except : 16 print er loopt i e t s mis b i j i g e l i j k aan, i # startoproep 18 main () De namen van de verschillende bestanden wordt bij het starten van het programma meegegeven: python mcopie.py resultaat appel peer kiwi Deze verschillende namen kunnen in het programma aangesproken worden via de lijst argv van de sys module. 77
78 9.7 Begrippen Een bestand, een file object, open(), close(). Lees- en schrijfoperaties: read(), readline(), write(), writeline(). Positionering in een bestand: seek(), tell(). Opvangen van uitzonderingen: try:... except:.... Tekstbestanden: geformatteerde in- en uitvoer. Python programma met argumenten. 78
79 10 Voorbeelden 10.1 Sorteren Opgave. Schrijf een programma dat een rij gehele getallen sorteert een eerste functie leest de rij gehele getallen; een tweede functie sorteert deze getallenrij van klein naar groot; een derde functie drukt de gesorteerde rij af. In het hoofdprogramma wordt het aantal ingelezen en worden de drie functies opgeroepen. # intsort. py: sorteren van een rij getallen 2 methode : sorteren door invoegen 4 k l e i n s te element zoeken in de resterende d e e l r i j en toevoegen aan de g e d e e l t e l i j k gesorteerde d e e l r i j 6 import numpy 8 def l e e s r i j (x,m) : print Geef een aantal gehele getallen 10 for i in range (m) : invoer = raw input ( str ( i )+ : ) 12 x [ i ] = int ( invoer ) 14 def drukrij ( r,m) : for i in range (m) : 16 print r [ i ], print 18 def zoekindexkleinste (a, n, vanaf ) : 20 indexkl = vanaf for i in range ( vanaf+1,n) : 22 if a [ i ] < a [ indexkl ] : indexkl = i 24 return indexkl 26 def s o r t e e r r i j (r, n) : for i in range (n 1) : 28 indexkleinste = zoekindexkleinste (r, n, i ) if r [ indexkleinste ]!= r [ i ] : 30 hulp = r [ i ] r [ i ] = r [ indexkleinste ] 32 r [ indexkleinste ] = hulp 34 def main ( ) : invoer = raw input ( Geef aantal : ) 36 m = int ( invoer ) a = numpy. zeros ( [m], int ) 38 l e e s r i j (a,m) b = l i s t (a) 40 s o r t e e r r i j (a,m) drukrij (a,m) 42 b. sort () drukrij (b,m) 79
80 44 # startoproep 46 main () Voorbeeld Merk op dat in Python een sorteermethode op lijsten beschikbaar is. Deze wordt in het programma ook getoond door de ingelezen array van getallen om te zetten naar een lijst en op deze lijst de sort() methode te activeren. In het programma wordt een docstring gebruikt, een triple-quoted string, eventueel over meerdere lijnen ("""..."""). Het biedt de mogelijkheid om wat uitgebreidere commentaar te schrijven, waarbij niet elke lijn met het commentaarsymbool (#) moet beginnen Binair zoeken Opgave. Schrijf een programma dat met een eerste functie een aantal gehele getallen inleest (maximum 20), die gesorteerd van klein naar groot ingegeven worden; eindigen met CTRL Z ; met een tweede functie een bijkomend geheel getal inleest; met een derde functie bepaalt of het laatst ingelezen getal in de rij voorkomt of niet (dit moet zo efficiënt mogelijk gebeuren); in het hoofdprogramma afdrukt of het getal aanwezig was of niet, en, zo ja op welke plaats in de rij. # binzoek. py: binair zoeken in een gesorteerde rij getallen 2 import numpy AANTAL = 50 4 def l e e s r i j (a) : 6 print Geef een aantal gehele getallen i = 0 8 while i < AANTAL : try : 10 invoer = raw input ( str ( i )+ : ) a [ i ] = int ( invoer ) 12 if i > 0 and a [ i ] < a [ i 1] : print vorige twee getallen niet in gesorteerde volgorde 14 else : i += 1 16 except EOFError : print 18 break return i 20 def drukrij ( r,m) : 22 for i in range (m) : print r [ i ], 24 print 26 def binzoek ( r, n, x) : 28 links = 0 80
81 rechts = n 1 30 if x < r [ links ] : return 0 if x > r [ rechts ] : return n 32 while links!= rechts : midden = ( links + rechts )/2 34 if r [ midden ] < x : links = midden else : rechts = midden 38 return links 40 def main ( ) : a = numpy. zeros ( [AANTAL], int ) 42 n = l e e s r i j (a) drukrij (a, n) 44 invoer = raw input ( Geef het te zoeken getal : ) zoekgetal = int ( invoer ) 46 index = binzoek (a, n, zoekgetal ) if index < n and a [ index ] == zoekgetal : 48 print zoekgetal, i s aanwezig op plaats, index, ( vanaf 0) else : 50 print zoekgetal, i s niet aanwezig (, index, ) if index == 0 : 52 print zoekgetal, i s kleiner dan eerste getal elif index == n : 54 print zoekgetal, i s groter dan l a a tste getal else : 56 print zoekgetal, kan toegevoegd worden op plaats, index 58 # startoproep main () Voorbeeld. Opzoeken van x = 74 en x = 40 in de gesorteerde rij: geeft als resultaat, respectievelijk 7 en Een adressenbestand Opgave. Schrijf een programma dat een aantal bewerkingen kan uitvoeren op adresgegevens. De invoer is een tekstbestand met per lijn een naam, voornaam, straat+nr, postcode, gemeente en telefoonnummer. De bewerkingen zijn: het inlezen van het bestand in een dictionary (sleutel is de tuple gevormd uit naam en voornaam), het maken van een gesorteerde lijst, het zoeken van een element op basis van naam en voornaam, het toevoegen van een element, het verwijderen van een element, het maken van een op postcode gesorteerde lijst en het bewaren van de gegevens op een tekstbestand. 1 # adres.py: beheer van adressen def inlezen () : 3 naw = dict () 81
82 try : 5 fin = open( adres. txt, r ) except : 7 print besta nd kan n i e t geopend worden exit (1) 9 while True : r l i j n = fin. readline () 11 if r l i j n == : break ; 13 l i j n = r l i j n. s trip () # einde lijn teken verwijderen velden = l i j n. s p l i t ( ; ) 15 velden [ 3 ] = int ( velden [ 3 ] ) # postcode omzetten naar int naw [ ( velden [ 0 ], velden [ 1 ] ) ] = velden [ 2 : ] 17 fin. close () print aantal adressen, len (naw) 19 return naw 21 def druk (n) : if n in naw : 23 geg = naw [ n ] print % 18s : % 18s %4d % 18s %s % \ 25 (n[0]+ + n [ 1 ], geg [ 0 ], geg [ 1 ], geg [ 2 ], geg [ 3 ] ) else : 27 print geen gegevens over, n 29 def l i j s t (naw) : namen = naw. keys () 31 namen. sort () for n in namen : 33 druk (n) return 35 def zoeken (naw) : 37 naam = raw input ( Naam: ) vnaam = raw input ( Voornaam : ) 39 druk ((naam, vnaam)) return 41 def p o s t l i j s t (naw) : 43 namen = naw. keys () spwt = naw. values () 45 elem = [ ] for q in spwt : 47 elem. append (q [ 1 ] ) # postcode comb = zip (elem, namen) 49 comb. sort () for p, n in comb : 51 druk (n) return 53 def toevoegen (naw) : 55 naam = raw input ( Naam: ) vnaam = raw input ( Voornaam : ) 57 straat = raw input ( Straat : ) 82
83 postco = raw input ( Postcode : ) 59 postcode = int ( postco ) gemeente = raw input ( Gemeente : ) 61 telefoon = raw input ( Telefoonnr : ) naw [ ( naam, vnaam ) ] = ( straat, postcode, gemeente, telefoon ) 63 return 65 def verwijderen (naw) : naam = raw input ( Naam: ) 67 vnaam = raw input ( Voornaam : ) if (naam,vnaam) in naw : 69 del naw [ ( naam,vnaam ) ] else : 71 print (naam, vnaam), niet aanwezig in dictionary return 73 def bewaren (naw) : 75 try : fuit = open ( nadres. txt, w ) 77 except : print besta nd kan n i e t gemaakt worden 79 return for n in naw : 81 geg = naw [ n ] r = l i s t (n) + l i s t ( geg ) 83 r [ 3 ] = str ( r [ 3 ] ) # postcode omzetten naar string print r 85 s = ; l i j n = s. join ( r ) + \n 87 fuit. write ( l i j n ) f u i t. close () 89 def main ( ) : 91 print Beheer van een adressenbestand while True : 93 print (0) : stoppen print (1) : inlezen van het bestand 95 print (2) : gesorteerde l i j s t print (3) : element zoeken 97 print (4) : element toevoegen print (5) : element verwijderen 99 print (6) : gegevens bewaren print (7) : op postcode gesorteerde l i j s t 101 keuze = raw input ( Keuze : ) k = int ( keuze ) 103 if k == 1 : naw = inlezen () elif k == 2 : l i j s t (naw) 105 elif k == 3 : zoeken (naw) elif k == 4 : toevoegen (naw) 107 elif k == 5 : verwijderen (naw) elif k == 6 : bewaren (naw) 109 elif k == 7 : p o s t l i j s t (naw) else : break 111 print Dank u wel 83
84 # startoproep 113 main () Een voorbeeld van een gegeven tekstbestand: Drieskens;Marc;Vendelstraat 15;3012;Wilsele;016/ Leupe;Dirk;Bergstraat 56;2500;Lier;03/ Ooms;Willy;Voort 27;2310;Rijkevorsel;03/
85 11 Ontwerpen van programma s 11.1 Een overzicht van de operatoren De operatoren gerangschikt van hoge naar lage prioriteit, met bijhorende associativiteit: functie/selectie () []. links macht ** rechts unair ~ + - rekenkundig * / % links + - links shift << >> links bit & links ^ links links vergelijking < <= > >= ==!= element/identiteit in not in is not is keten logisch not links and links or links Merk op dat elk van de tekens - en + tweemaal voorkomt. De context van het desbetreffende teken in het programma bepaalt om welke operator het gaat. Operatoren *, + en % kunnen ook op strings toegepast worden. Daarnaast zijn er nog de toekenningssymbolen: =, +=, -=, *=, /=, %=, **=, <<=, >>=, &=, =, ^= De keywords van de taal Sommige woorden zijn gereserveerd als keyword; zij hebben een vaste betekenis en mogen daarom niet als naam voor iets anders (bijvoorbeeld variabele) gebruikt worden. Constanten : True False None Operatoren : and or not as in is Controle statement : break continue def elif else for if pass return while Statements : del exec from import lambda print De rest : assert class except finally global raise try with yield Daarnaast zijn er een heleboel type-functies die best ook niet als naam van een variabele gebruikt worden: int(), float(), complex(), str(), chr(), ord(), list(), tuple(), dict() Leesoefening Opgave. Verklaar de werking van volgend programma. # leesex. py : leesoefening 2 def beker (a, q, z ) : g = 7 4 z [ 0 ] = z [ 2 ] z [ 1 ] a += g 6 q = g z [ 2 ] = float ( g ˆ 0x2 ) 85
86 8 return q/2, a/2 def pint ( f, t ) : 10 m = int ( t f ) f = t 12 return m def glas (b, w) : 14 global x f = pint (b, x) 16 w[ 2 ] = w[ 2 ] + x x = x + w[ 1 ] 18 return b<<1 20 def main ( ) : f = 4 22 x = 1.0 y = [ 2.0, 5.0, 8. 0] 24 print f=, f, x=, x, y=, y x, f = beker ( f, x, y) 26 print f=, f, x=, x, y=, y f = glas ( f, y) 28 print f=, f, x=, x, y=, y # startoproep 30 main () 11.4 Ontwerp Voor het ontwerpen en schrijven van computerprogramma s zijn twee zaken nodig: een goed begrip van de elementen van een programmeertaal; het begrijpen van de definitie en structuur van het probleem dat moet opgelost worden of de taak die moet uitgevoerd worden. In de vorige hoofdstukken werden de basiselementen van de programmeertaal Python uitgelegd. Daarnaast zijn dus technieken nodig om een probleem te analyseren en daaruit een oplossing af te leiden welke kan omgevormd worden tot een programma. Volgens G. Polya (eind jaren veertig) zijn er 4 stappen nodig om een algoritme te ontwerpen: 1. Begrijp het probleem. 2. Tracht een idee te vormen over hoe een algoritmische procedure het probleem zou kunnen oplossen. 3. Formuleer het algoritme en schrijf het neer als een programma. 4. Evalueer het programma op nauwkeurigheid en op de mogelijkheden om het als middel te gebruiken bij het oplossen van andere problemen. Voor de meeste problemen kan de ontwerper een iteratieve oplossingsbenadering toepassen. Men begint met een vereenvoudigd probleem en construeert hiervoor een betrouwbare oplossing. Daardoor krijgt men meer vat op het probleem. Dit beter begrijpen kan dan gebruikt worden om meer details in te vullen en een verfijnde oplossingsprocedure uit te denken, totdat men komt tot een bruikbare oplossing voor het originele realistische probleem. De eerste twee stappen kunnen in praktijk zeer moeilijk zijn en in het geval van enkele wiskundige problemen, zal de oplossing equivalent zijn met het ontdekken en bewijzen van nieuwe stellingen voordat een computerprogramma kan geschreven worden. Het is bijvoorbeeld tot op dit moment niet geweten of volgende procedure altijd zal stoppen voor een willekeurige initiële waarde. # stop.py : stopt dit programma (Collatz) 86
87 2 import sys def main ( ) : 4 stap = 0 getal = int ( sys. argv [ 1 ] ) 6 while getal!= 1 : if getal%2 == 0 : 8 getal = getal /2 else : 10 getal = 3 getal+1 print getal, 12 stap += 1 print 14 print programma stopt na, stap, stappen # startoproep 16 main () Niet alle problemen kunnen opgelost worden door middel van computerprogramma s. En zelfs wanneer een algoritme bestaat, is het niet altijd mogelijk dit algoritme te implementeren in een programma omwille van beperkingen van de grootte van het werkgeheugen en de beschikbare rekentijd Structuur van een programma Men kan weinig algemene richtlijnen geven om een programma te structureren, omdat de structuur afhankelijk is van het origineel probleem en het algoritme dat gebruikt wordt. Toch is het nuttig om een programma op te delen in drie fazen: Initialisatie : declaratie en initialisatie van de variabelen. Het is nuttig om alle beschikbare informatie in te voeren voordat de berekeningen starten, zodat controles op juistheid van gegevens kan gebeuren. Een complexe simulatie uitvoeren kan uren duren en het zou spijtig zijn dat het programma halverwege vastloopt omdat de gebruiker een foutieve invoer doet. Data verwerking : het grootste gedeelte van het programma. De implementatie van de oplossingsprocedure met behulp van functies, iteratie-lussen en keuze-statements. Stockeren van de resultaten : op het einde van het programma. Het uitschrijven van de resultaten naar het beeldscherm en/of naar een bestand. Opgave. Schrijf een programma dat de elementen van een vierkante matrix invult zodat de som van elke rij gelijk is aan de som van elke kolom (een magisch vierkant). Algoritme. In het geval dat het aantal rijen (kolommen) oneven is, bestaat er een eenvoudige methode. De getallen 1, 2,..., n 2 worden ingevuld waarbij de plaats op de volgende manier berekend wordt: 1. begin in het midden van de laatste rij; 2. het volgend element wordt ingevuld linksboven het huidig element; 3. tenzij buiten de grenzen van het vierkant gegaan wordt, in dat geval is het de laatste rij en/of laatste kolom; 4. indien de plaats reeds ingevuld is, dan wordt het volgende element ingevuld net onder het huidig element; 5. tenzij buiten de grens van het vierkant gegaan wordt, in dat geval is het de eerste rij. 87
88 # vierkant. py invullen magisch vierkant met oneven grootte 2 import numpy 4 def hoegroot () : invoer = raw input ( Geef grootte : ) 6 n = int ( invoer ) if n % 2 == 0 : 8 print Geen oneven getal, n exit () 10 return n 12 def afdrukken (a, n) : for i in range (1,n+1) : 14 for j in range (1,n+1) : a [ i ] [ 0 ] += a [ i ] [ j ] 16 a [ 0 ] [ j ] += a [ i ] [ j ] print %3d % (a [ i ] [ j ] ), 18 print %5d % (a [ i ] [ 0 ] ) a [ 0 ] [ 0 ] += a [ i ] [ 0 ] 20 for j in range (1,n+1) : print %3d % (a [ 0 ] [ j ] ), 22 print %5d % (a [ 0 ] [ 0 ] ) 24 def invullen (a, n) : n2 = n n 26 k = 1; j = n/ i = n while k <= n2 : 30 print i=, i, j=, j, k=, k a [ i ] [ j ] = k 32 k += 1 vi, vj = i, j 34 i = 1 j = 1 36 if i == 0 : i = n 38 if j == 0 : j = n 40 if a [ i ] [ j ]!= 0 : i = vi if i > n : i = 1 44 j = vj 46 def main ( ) : n = hoegroot () 48 a = numpy. zeros ( [ n+1,n+1], int ) invullen (a, n) 50 afdrukken (a, n) # startoproep 52 main () 88
89 Het resultaat voor n = 3: Deze matrix wordt in het werkgeheugen als één lange rij gestockeerd:? 7 5 3? 2 9 4? Het resultaat voor n = 5 (de som is telkens 65):
90 A Practicum. A.1 Editeren en uitvoeren Om de applicatie te starten : dubbel klik op het Spyder icoon. Het basisscherm bevat twee deelvensters met bovenaan drie lijnen; links kan een programma ingetikt worden; rechts is een venster voorzien waarin de interpreter opgestart is. In dit rechtse venster wordt een tabblad bijgecreëerd wanneer een programma uitgevoerd wordt. Eventuele foutmeldingen worden daar ook getoond. 1. De eerste lijn geeft de naam van het programma: Spyder. 2. Op de tweede lijn: een aantal menu-knoppen: File, Edit,..., Run, Op de derde lijn: een aantal iconen. Door op één van de menu-knoppen op de tweede lijn te klikken, verschijnt er een submenu. Om een programma in te tikken en te laten uitvoeren, kan volgende sequentie gebruikt worden: 1. File : New file 2. Tik het programma in. Voor de indentatie, gebruik indien nodig de Tab toets. Met de Backspace kan terug naar een vorig indentatie-niveau gegaan worden. 3. File : Save as 4. Run : Run In het rechtse venster wordt een nieuw tabblad actief. Bij (syntax-)fouten worden deze hier gemeld. In dit venster kan de invoer gegeven worden en wordt ook de uitvoer getoond. 5. Bij eventuele syntax-fouten (melding in tabblad van rechts deelvenster): verbeter deze en herhaal vorige stap tot je een succesvolle uitvoering hebt. 6. De applicatie beëindigen kan met File : quit Deze acties kunnen ook via de iconen van de derde lijn gestart worden: 1. New: om een nieuw programma beginnen in te tikken (voorlopig geen bestandsnaam); 2. een bestand laden in de editor; 3. ingetikte tekst (bronprogramma) in een bestand bewaren; 4. niet nodig (alleen voor programma s bestaande uit meerdere bronbestanden); 5. het ingeladen bestand afdrukken; 6. knoppen voor commentaar en indentatie; 7. knoppen voor zoeken en vervangen van tekstdeeltjes; 8. uitvoeren van het programma (wit lopertje in groen cirkeltje); 9. debuggen van het programma (voor gevorderden). Een bronbestand afdrukken kan met File, Print; kies hierbij HP LaserJet 400 op rodin. Belangrijke opmerking. De quotering voor het labo is gebaseerd op permanente evalutie. Aanwezigheid in het labo is dus verplicht; op het einde van het semester een aantal listings afgeven is NIET voldoende. Aanwezigheid is echter niet voldoende: een labo moet voorbereid worden en tijdens het labo moet een zekere vorm van activiteit ontplooid worden. Een labo voorbereiden wil zeggen: het bijhorende hoofdstuk bestudeerd hebben (door bijvoorbeeld onder andere aandachtig het hoorcollege gevolgd te hebben) en door op papier reeds een aanzet van een programma gemaakt te hebben. 90
91 A.2 Practicumzitting 1: eenvoudige berekeningen. 1. Schrijf een programma dat drie getallen inleest, grote basis (B), kleine basis (b) en hoogte (h) van een trapezium, de oppervlakte van de trapezium berekent B+b 2 h, en het resultaat uitschrijft. 2. Schrijf een programma dat twee getallen inleest, zijde (z) en hoogte (h) van een piramide met vierkantig grondvlak, het volume van de piramide berekent 1 3 z2 h, en het resultaat uitschrijft. 3. Schrijf een programma dat twee gehele getallen inleest en het product van deze twee getallen berekent; twee volgende gehele getallen inleest en het product van deze twee getallen berekent; de eindsom berekent van deze twee producten; een reëel getal inleest om daarmee het percentage op de som te berekenen; de eindsom, het percentage en de som van deze eindsom en percentage uitschrijft. A.3 Enkele kleine opgaven. Practicumzitting 2: 1. Lees vier gehele getallen a, b, c en d. Bereken of a kleiner is dan d; of (a + 1) groter is dan c; of a gelegen is in het interval [b, c]; of d gelegen is buiten het interval [b, c]; of a kleiner is dan b en c of d groter is dan b en c. 2. Lees drie positieve gehele getallen en ga na of deze getallen een pythagorisch drietal vormen: a 2 = b 2 + c 2. De volgorde waarin de getallen ingelezen worden, is willekeurig. 3. Lees een jaartal in en test of dit een schrikkeljaar is of niet. Een schrikkeljaar is een jaartal deelbaar door 4 maar niet door 100, of deelbaar door Lees een bedrag in eurocent in (een geheel getal). Bereken het aantal biljetten (e 20 ene5) en het aantal muntstukken (e 1, 10 cent, 5 cent en 1 cent) dat je nodig hebt om dit bedrag uit te betalen. 5. Lees twee positieve getallen tussen 20 en 99 in. Om het product van deze twee getallen te berekenen kan de Vedische methode (of kruisvermenigvuldiging) gebruikt worden: bereken de cijfers van eenheden van beide getallen en vermenigvuldig deze; het cijfer van de eenheid van dit getal is de eenheid van het product; het cijfer van het tiental van dit getal wordt overgedragen; bereken ook de cijfers van de tientallen van beide getallen; maak de som van het product van het tiental van het ene getal en de eenheid van het andere getal, het product van het tiental van het andere getal en de eenheid van het eerste getal en het cijfer dat overgedragen is van de vorige stap; het cijfer van de eenheid van dit getal is het tiental van het product; het cijfer van het tiental van dit getal wordt overgedragen; bereken het product van tientallen van beide getallen en tel hierbij het overdragen cijfer van de vorige stap op; dit resultaat vormt het honderdtal en eventueel duizendtal van het product. Voorbeeld: product van 57 en 83: eenheden 7 en 3 : product 21, dus eenheid 1 en over te dragen 2 tientallen 5 en 8, eenheden 7 en 3 : of 73 dus tiental 3 en over te 91
92 dragen 7 tientallen 5 en 8 : product of 47 uiteindelijk product : Practicumzitting 3: 1. Lees twee getallen m en n in (met m n) en bereken n i=m i2. Uitbreiding: bereken l = (n m)/2; bereken de totale som in twee opeenvolgende lussen: van i = m tot m + l: m.b.v. een for-lus; van i = m + l + 1 tot n: m.b.v. een while-lus. 2. Genereer de rij van Fibonnacci. De eerste term is gelijk aan 0. De tweede term is gelijk aan 1. Vanaf de derde term is elke term gelijk aan de som van de twee voorgaande termen. Bereken ook telkens het quotiënt F n /F n 1. Het programma stopt wanneer het verschil van het huidige quotiënt met het vorige quotiënt kleiner geworden is dan 1.0e-4. (Dit quotiënt is gelijk aan 2 cos36 of ) 3. Lees 3 getallen in: de lengtes van twee zijden a en b van een willekeurige driehoek en de grootte van de ingesloten hoek γ (in graden). Bereken uit deze drie getallen de lengte van de derde zijde (c 2 = a 2 + b 2 2ab cosγ) en de grootte van de twee andere hoeken (a/ sin α = b/ sinβ = c/ sinγ). Practicumzitting 4: 1. Opgave op operatoren en controle structuren. 2. Lees twee getallen n (met maximumwaarde 5) en x in en een getallenrij a n a n 1 a n 2... a 2 a 1 a 0. Bereken hieruit y = a n x n + a n 1 x n a 1 x + a 0 Maak hierbij gebruik van de methode van Horner: y = (... ((a n x + a n 1 )x + a n 2 )x a 1 )x + a 0 A.4 Practicumzitting 5: eenvoudige algoritmes. 1. Schrijf een programma om na te gaan of een getal een priemgetal is. Bouw het programma op met behulp van functies: lees om het getal in te lezen; priem om na te gaan of dit getal een priemgetal is (test of het getal 2 en de oneven getallen tussen 3 en n/2 delers zijn); schrijf de conclusie in het hoofdprogramma uit. 2. Schrijf een programma dat de n n de machtswortels berekent van een complex getal. Het complex getal en de waarde voor n moeten ingelezen worden. in een eerste functie wordt het complex getal (a + bj) omgezet naar zijn modulus r en argument θ: r = a 2 + b 2 en θ = arctan b a een tweede functie berekent de verschillende wortels in poolcoördinaten: t k = n r en φ k = θ + 2kπ n 92 met k = 0, 1,,n 1
93 de poolcoördinaten worden terugomgezet naar cartesische coördinaten c k + d k j: c k = t k cosφ k en d k = t k sin φ k met k = 0, 1,,n 1 de lijst met wortels wordt in het hoofdprogramma afgedrukt. A.5 Practicumzitting 6: numeriek integreren: de regel van Simpson. Bereken de bepaalde integraal van f(x) tussen a en b met behulp van de regel van Simpson. De x-as tussen a en b wordt verdeeld in 2n gelijke stukken met h = (b a)/2n en x 0 = a, x 2n = b. I = b a Test de procedure met een aantal functies: f(x)dx = h [ (f(x0 ) + f(x 2n ) 3 +4(f(x 1 ) + f(x 3 ) + f(x 5 ) f(x 2n 1 )) +2(f(x 2 ) + f(x 4 ) + f(x 6 ) f(x 2n 2 )) ] f(x) = sin 2 (x) met a = 0.0 en b = 1.0 f(x) = exp( x 2 ) met a = 1.0 en b = 1.0 f(x) = exp(x)cos(x) met a = 0.0 en b = 1.0 Ontwikkel dit programma via stapsgewijze verfijning: 1. Eenvoudig begin: Schrijf een functie men naam fun(x) waarin de waarde van de opgegeven functie berekend wordt voor een gegeven argument x. Deze waarde wordt via return teruggegeven. Schrijf een main functie waarin de waarden van a en b ingelezen worden. In deze functie wordt de som berekend van de functiewaarde van a en de functiewaarde van b in de variabele resultaat. De resultaat wordt uitgegeschreven. 2. Eerste uitbreiding: Declareer een variabele n in de main functie met waarde gelijk aan 8. Bereken de stap h = (b a) 2 n. Bereken in de variabele onevensom de som van de functiewaarden in x tussen a + h en b h dmv. een iteratie-statement waarbij x telkens met h verhoogd wordt. Schrijf naast resultaat de resulterende onevensom uit. 3. Tweede uitbreiding: Verander de lus waarin onevensom variabele berekend wordt door bij x telkens 2 h bij te tellen. Voeg een tweede lus bij om in de variabele evensom de som van de functiewaarden x tussen a + 2h en b 2h te berekenen waarbij x telkens met 2 h verhoogd wordt. Schrijf naast resultaat de resulterende onevensom en evensom uit. 4. Derde uitbreiding: bereken h 3 (resultaat + 4 onevensom + 2 evensom) en schrijf deze waarde uit. 5. Tot slot Voeg een overkoepelende while-lus toe waarin n telkens verdubbeld wordt; de stopvoorwaarde voor deze lus is afhankelijk van de absolute waarde van het relatief verschil van de huidige benaderende waarde voor de integraal en de vorige benaderende waarde (wanneer dit verschil kleiner is dan ǫ = 1.0e 4, mag er gestopt worden). A.6 Practicumzitting 7: een-dimensionale arrays. 1. Recamán reeks. De n-de term wordt berekend uit de voorgaande term door van deze voorgaande term n af te trekken of n bij op te tellen. Eerst wordt de aftrekking geprobeerd. Als 93
94 dit resultaat een positief getal is dat nog niet in de reeks voorkomt, is de n-de term gevonden. In het andere geval wordt in plaats van de aftrekking de optelling met n uitgevoerd om de n-de term te bepalen. De 0-de term van de reeks is gelijk aan 0. Schrijf een programma dat deze reeks berekent. De berekende elementen van de reeks worden in een ééndimensionale array van maximaal 100 elementen gestockeerd. Deel het programma op in een aantal korte functies. 2. Lees een rij van maximaal 30 gehele getallen in een één-dimensionale array. Sluit de invoer van getallen af met het getal 0. Bepaal voor elk element uit de rij hoeveel kleinere getallen er in de rij op dat element volgen (definieer hiervoor een functie). 3. Lees een geheel getal N in. Genereer een reeks van N willekeurige getallen tussen 0 en 9 (zie voorbeeld p. 25). Schrijf een functie die een array op nul initialiseert en een tweede functie die in deze array het aantal maal dat elk cijfer voorkomt, telt. Schrijf als resultaat een tabel uit met voor elk cijfer het bijhorende aantal. A.7 Practicumzitting 8: beoordeling van testen. Een groep van N (met N 20) onderdelen wordt onderworpen aan M (met M 15) testen. Per test zijn er drie mogelijke vaststellingen: 0 : geen fout; 1 : een lichte fout; 3 : een zware fout. Deze informatie moet per onderdeel en per test ingegeven worden door middel van een drietal: onderdeelnummer testnummer testresultaat Wanneer het testresultaat gelijk is aan nul, moet het corresponderende drietal niet ingegeven worden. De invoer kan afgesloten worden met het drietal < 000 >. Op basis van de verschillende testresultaten per onderdeel kan het onderdeel beoordeeld worden: { slecht: één of meer zware fouten en/of drie of meer lichte fouten; goed: de andere gevallen. De verwerking moet resulteren in volgende uitvoer: 1. Per onderdeel: een lijn met het onderdeelnummer, de resultaten van elke test en de beoordeling. 2. Per test: een lijn met het aantal onderdelen zonder fouten, het aantal met lichte en het aantal met zware fouten Voorbeeld: Invoer Uitvoer slecht goed slecht goed slecht Merk op. Deze matrix moet eerst op 0 geinitialiseerd worden. Tip. Construeer tijdens invoer een matrix met op de i-e rij en de j-e kolom het resultaat van de j-e test op onderdeel i (mat[onderdeelnummer][testnummer] = resultaat). A.8 Practicumzitting Opgave op het gebruik van functies en arrays. 2. Afwerken van beoordelen van testen. 94
95 A.9 Practicumzitting 10: strings. Schrijf een programma met functies die twee strings inleest. De twee in te lezen strings bevatten tekens in alfabetische volgorde. Daarna worden twee functies opgeroepen: 1. De eerste functie (telklinker) heeft als argument de een ingelezen string. Deze functie telt het aantal klinkers (aeiou) in deze string en geeft dit aantal als resultaat terug. 2. De tweede functie (meng) heeft twee argumenten: de twee inlezen strings. Deze functie mengt de twee strings in een nieuwe string. Tijdens het mengen worden de twee strings element per element afgegaan en toegevoegd aan de nieuwe string zodanig dat de elementen in deze nieuwe string ook in alfabetische volgorde staan. De resulterende string wordt teruggegeven aan het hoofdprogramma. (Kan het programma efficiënter gemaakt worden door tijdens het mengen voor het resultaat een andere datastructuur te gebruiken, die dan achteraf omgezet wordt in een string?) Het resultaat (totaal aantal klinkers in de twee strings en de resulterende string) wordt afgedrukt in de functie drukres. Voorbeelden: invoer: dipqs bcortxy invoer: adpquv cepxyz uitvoer: 2 b c d i o p q r s t x y uitvoer: 3 a c d e p p q u v x y z Tip. Gebruik één lus om de nieuwe lijst op te bouwen en waarin de twee gegeven strings afgegaan worden, elk met een eigen teller, bijvoorbeeld i en j. A.10 Practicumzitting 11: bestand met woorden. Gegeven een tekstbestand met naam woorden.txt met per lijn een woord. Schrijf een aantal functies: 1. lees() leest de woorden van het tekstbestand en voegt de woorden met een lengte meer dan drie toe aan een lijst; resultaat van deze functie is de lijst met woorden; 2. is_palindroom(w) test of een woord een palindroom is, d.i. het woord en het omgekeerde woord zijn gelijk aan elkaar, bijv. negen; 3. caesar(w,s) vervangt elke letter in het woord w door de s-e volgende letter; indien hierbij voorbij de letter z geteld wordt, wordt van voorafaan verder gegaan; (uitbreiding: bij negatieve s wordt naar voor geteld); Schrijf een hoofdprogramma: 1. via de functie lees() wordt een lijst met woorden gemaakt; 2. er wordt een tekstbestand resultaat.txt gecreëerd; 3. voor elk woord in de lijst wordt nagegaan of dit een palindroom is; indien dat zo is, wordt dat woord toegevoegd aan het resultaatbestand; 4. er wordt een getal inlezen dat als verschuivingswaarde gebruikt wordt; 5. voor elk woord in de lijst wordt nagegaan of de caesar-codering met de ingelezen verschuivingswaarde zelf een woord is (dus voorkomt in de lijst van woorden); indien dat zo is, wordt het woord en zijn caesar-codering toegevoegd aan het resultaatbestand; 6. het resultaatbestand wordt afgesloten. Uitbreiding: lees de caesar-coderingen van het resultaatbestand en bereken op basis van deze coderingen de gebruikte verschuivingswaarde. 95
96 A.11 Practicumzitting 12: plaatsreservatie. In een ruimte zijn een aantal rijen (maximum 6, dus aanduiding tussen letters a en f ) met per rij een aantal zitplaatsen (maximum 9) beschikbaar. De effectieve grootste rijletter en het effectief aantal zitplaatsen moeten ingelezen worden, bijvoorbeeld rijen tot en met letter b met elk drie zitplaatsen. 1. Het programma roept een functie reserveren op. In deze functie wordt opeenvolgend plaatsindicaties gevraagd. Een plaatsindicatie is een string die bestaat uit twee tekens: eerste teken is een letter en geeft de rij aan; tweede teken is een cijfer en geeft de plaats in de rij aan. Bijvoorbeeld, b6 duidt de 6e plaats in de tweede rij aan. Indien de plaats vrij is, wordt de naam gevraagd (een string) en ingevuld op de aangegeven plaats. Indien de plaats reeds bezet is, wordt dit door de functie gemeld. Tip: gebruik als datastructuur een dictionary: de plaatsindicatie is de sleutel; de naam de waarde. Wanneer de invoer beëindigd wordt met het intikken van het EOF teken ( Ctrl Z Enter ), genereert het programma een gesorteerde tabel (op sleutel) met de reservaties: plaatsindicatie naam Voeg een functie bewaren() toe, die de reservaties wegschrijft op een bestand reservatie.txt. Zo n lijn in dit bestand bevat plaatsindicatie naam Als extra wordt op de eerste lijn de maximale rijletter en maximale plaatsnummer weggeschreven. 2. Voeg een functie inlezen() toe die het bestand reservatie.txt leest en invult in de dictionary, indien dit bestand bestaat. Indien het bestand niet bestaat, stopt het programma. Voeg een functie schema() toe die de reservaties afdrukt per rij. Tip: splits de sleutel in een letter en een cijfer, zodat per rij (overeenkomend met een letter) de verschillende plaatsen kunnen afgedrukt worden, met een veldbreedte van 10. Indien er op een specifieke plaats in een rij geen naam ingevuld is, druk dan 10 spaties af marianne jos janneke marie-rose 3. Plaatsreservatie met gelijkmatige gewichtsverdeling. Het effectieve aantal zitplaatsen op een rij is even. In plaats van de plaatsindicatie in te lezen, moet bij een reservatie het gewicht van de persoon in kwestie opgevraagd worden. Op basis daarvan moet een plaats gezocht zodat het totale gewicht van de linkerkant ongeveer gelijk blijft aan het totale gewicht van de rechterkant. Het waardeveld in de dictinary is nu een tuple. Elk tuple bevat twee velden: een string voor de naam van de persoon, en een float voor het gewicht. Bij het einde van het programma worden de reservaties afgedrukt zoals in vorige oefening en ook de totale massa van de linkerkant en de rechterkant. Uitbreiding: het aantal rijen is even en er moet ook rekening gehouden worden met een gelijkmatige gewichtsverdeling tussen voor- en achterkant. A.12 Extra oefening: lineaire regressie. 1. Maak een tekstbestand met een aantal meetpunten: op elke lijn twee reële getallen. 2. Schrijf een programma dat het tekstbestand leest en de getallen stockeert in twee arrays: x en y. Het aantal meetpunten is n. Bereken dan de lineaire regressie: y = ax + b a = n xy ( x)( y) n x 2 ( x) 2 b = ( 96 y)( x 2 ) ( x)( xy) n x 2 ( x) 2
97 Creëer een tekstbestand met per lijn drie getallen: de meetpunten x i en y i en de bijhorende berekende waarde y i = ax i + b. 3. Schrijf een programma dat het tekstbestand leest en een tabel afdrukt met per lijn de drie getallen. Bereken ook de totale kwadratische fout (y i y i )2. 97
98 B Python: installatie op een Windows systeem B.1 Python en IDLE 1. Ga naar 2. Klik op de link python2.7.6: je krijgt een lijst van mogelijke versies in functie van besturingssysteem { window x86 MSI installer (32 bit) 3. Selecteer de juiste optie: window x86-64 MSI installer (64 bit) 4. Door het gedownloade bestand uit te voeren met de standaard instellingen, worden de nodige bestanden in een map c:\python27 geïnstalleerd. 5. numpy: download van uit de folder numpy win32-superpack-python2.7.exe Een 64-bit versie is te vinden op: Voor python 2.7 kies je numpy-unoptimized win-amd64-py2.7.exe. 6. Door het gedownloade bestand uit te voeren met de standaard instellingen, worden alle nodige bestanden in een submap van c:\python27 geïnstalleerd. B.2 IDE: spyder 1. Download PyQT4 van Onder de rubriek Binary Packages, kies de juiste versie voor python 2.7: { PyQt gpl-Py2.7-Qt4.8.5-x32.exe (32 bit) PyQt gpl-Py2.7-Qt4.8.5-x64.exe (64 bit) 2. Door het gedownloade bestand uit te voeren met de standaard instellingen, worden alle nodige bestanden in een submap van c:\python27 geïnstalleerd. 3. Download spyder van Zoek in Current downloads naar spyder { spyder win32.exe (32 bit) spyder win-amd64.exe (64 bit) 4. Door het gedownloade bestand uit te voeren met de standaard instellingen, worden alle nodige bestanden in een submap van c:\python27 geïnstalleerd. 5. Je kan spyder starten via het startmenu onder het menu spyder met als submenu Spyder(full). 98
Constanten. Variabelen. Expressies. Variabelen. Constanten. Voorbeeld : varid.py. een symbolische naam voor een object.
een symbolische naam voor een object. Variabelen Constanten Variabelen Expressies naam : geeft de plaats in het geheugen aan waarde : de inhoud van het object identifier : een rij van letters en/of cijfers
Controle structuren. Keuze. Herhaling. Het if statement. even1.c : testen of getal even of oneven is. statement1 statement2
Controle structuren De algemene vorm: 1 bloks door middel van indentatie Keuze Herhaling if expressie :...... In de volgende vorm is het else gedeelte weggelaten: if expressie :... Het if keuze- of conditioneel
5.7.1 Priemgetallen Driehoek van Pascal Matrix-product Begrippen... 42
Inhoudsopgave 1 Algoritmes en computerprogramma s 1 1.1 Basiselementen van een computer............................ 1 1.2 Algoritmes........................................ 1 1.3 Som van twee getallen..................................
Niet-numerieke data-types
Intern wordt een karakter voorgesteld als een rij van acht bits, Niet-numerieke data-types string de letter a 01100001 0110 0001 0x61 97 Bij interpretatie van de inhoud van een byte als een geheel getal,
Vakgroep CW KAHO Sint-Lieven
Vakgroep CW KAHO Sint-Lieven Objecten Programmeren voor de Sport: Een inleiding tot JAVA objecten Wetenschapsweek 20 November 2012 Tony Wauters en Tim Vermeulen [email protected] en [email protected]
Arrays. Complexe datastructuren. Waarom arrays. Geen stijlvol programma:
Geen stijlvol programma: Complexe datastructuren Arrays vijf verschillende variabelen voor iets dat als één rij getallen bestempeld wordt; onbruikbaar wanneer het over meer getallen (bijvoorbeeld ) gaat.
OEFENINGEN PYTHON REEKS 1
Vraag 1: Expressies & Types OEFENINGEN PYTHON REEKS 1 Python maakt gebruik van enkele vaak voorkomende (data)types. Zo zijn er integers die behoren tot de gehele getallen (VB: 3), zijn er float s die behoren
Persistentie via bestanden. Bestanden
programma is transient Persistentie via bestanden Administratieve gegevens zijn verzameld in het file-object: o.a. waar ergens op de disk de data van het bestand te vinden is. invoer van de gebruiker programma
OEFENINGEN PYTHON REEKS 1
OEFENINGEN PYTHON REEKS 1 Vraag 1: Python als een eenvoudige rekenmachine Python maakt gebruik van enkele vaak voorkomende (data)types. Zo zijn er integers die behoren tot de gehele getallen (VB: 3) en
PYTHON REEKS 1: BASICS. Mathias Polfliet
PYTHON REEKS 1: BASICS Mathias Polfliet [email protected] EENVOUDIGE REKENMACHINE 2 soorten getallen Getallen Z -> integers (gehele getallen) Getallen R -> floating points (reële getallen) Door beperkte
PROS1E1 Gestructureerd programmeren in C Dd/Kf/Bd
Inhoudsopgave 1 Inleiding... 1 2 Toekenning- en herhalingsopdrachten (for loop)... 2 2.1 De wet van Ohm... 3 2.2 De spaarrekening... 3 2.3 De transformator... 3 3 Keuze- en herhalingsopdrachten (if, switch,
Interne voorstelling. types en conversies. Binaire en andere talstelsels. Voorstelling van gegevens: bits en bytes
Interne voorstelling types en conversies Het geheugen wordt ingedeeld in een aantal gebieden van gelijke grootte. Een gebied van 8 bits noemt men een byte (nible een groep van bits). Een (computer)woord
Python. Vraag 1: Expressies en types. Vraag 1 b: Types -Ingebouwde functies- Vraag 1 a 3/10/14
Python Vraag 1: Expressies en types Integrated Development Environment (IDE): Ø Wing 101 (gratis te downloaden op www.wingware.com) Oefeningen in de shell >> noemen we de prompt Python commando s = expressies
17 Operaties op bits. 17.1 Bitoperatoren en bitexpressies
17 Operaties op bits In hoofdstuk 1 is gezegd dat C oorspronkelijk bedoeld was als systeemprogrammeertaal om het besturingssysteem UNIX te implementeren. Bij dit soort toepassingen komt het voor dat afzonderlijke
HOOFDSTUK 3. Imperatief programmeren. 3.1 Stapsgewijs programmeren. 3.2 If Then Else. Module 4 Programmeren
HOOFDSTUK 3 3.1 Stapsgewijs programmeren De programmeertalen die tot nu toe genoemd zijn, zijn imperatieve of procedurele programmeertalen. is het stapsgewijs in code omschrijven wat een programma moet
OEFENINGEN PYTHON REEKS 1
Vraag 1: Expressies & Types OEFENINGEN PYTHON REEKS 1 Python maakt gebruik van enkele vaak voorkomende (data)types. Zo zijn er integers die behoren tot de gehele getallen (VB: 3), zijn er float s die behoren
Lab Webdesign: Javascript 3 maart 2008
H5: OPERATORS In dit hoofdstuk zullen we het hebben over de operators (of ook wel: operatoren) in JavaScript waarmee allerlei rekenkundige en logische bewerkingen kunnen worden uitgevoerd. Daarbij zullen
Variabelen en statements in ActionScript
Ontwikkelen van Apps voor ios en Android Variabelen en statements in ActionScript 6.1 Inleiding Als we het in de informatica over variabelen hebben, bedoelen we een stukje in het geheugen van de computer
Als een PSD selecties bevat, deelt de lijn van het programma zich op met de verschillende antwoorden op het vraagstuk.
HOOFDSTUK 3 3.1 Stapsgewijs programmeren In de vorige hoofdstukken zijn programmeertalen beschreven die imperatief zijn. is het stapsgewijs in code omschrijven wat een programma moet doen, net als een
Een korte samenvatting van enkele FORTRAN opdrachten
Een korte samenvatting van enkele FORTRAN opdrachten Inhoud 1 Introductie 3 2 De structuur van een FORTRAN programma 3 3 Datatypen, variabelen en declaraties 3 4 Expressies-volgorde van uitwerking 4 5
Inhoud. Informatica. Hoofdstuk 5 Scripting. Context. Editor voor Programmeercode. Scripting 1
5.1 5.2 1rste BAC Biologie Hoofdstuk 5 Inhoud Inleiding Programeerconstructies functies variabelen (toekenning) statements (print, ) controlestructuren (if, while, until, for) Oefeningen 5.3 5.4 "functionzero.zip"
Java Les 3 Theorie Herhaal structuren
Java Les 3 Theorie Herhaal structuren Algemeen Een herhaal structuur een is programmeertechniek waarbij bepaalde Java instructies worden herhaald net zo lang tot een bepaalde voorwaarde is bereikt. Een
[8] De ene 1 is de andere niet
[8] De ene 1 is de andere niet Volg mee via 08_Types.py In de volgende leerfiche gaan we rekenen met Python. Dat kan je in een programma doen, maar dat kan je ook gewoon vanuit het Shell-venster doen.
DE INTERACTIEVE SHELL
Hoofdstuk2 De interactieve shell 6 Hoofdstuk 2 DE INTERACTIEVE SHELL In dit hoofdstuk behandelen we: Integers (gehele getallen) en getallen met drijvende komma Expressies Waarden Operatoren Het evalueren
Programmeermethoden NA. Week 5: Functies (vervolg)
Programmeermethoden NA Week 5: Functies (vervolg) Kristian Rietveld http://liacs.leidenuniv.nl/~rietveldkfd/courses/prna/ Bij ons leer je de wereld kennen 1 Functies Vorige week bekeken we functies: def
VAN HET PROGRAMMEREN. Inleiding. Het spiraalmodel. De programmeertaal. vervolgens de berekening van het totale bedrag, incl. BTW:
OVERZICHT VAN HET PROGRAMMEREN Inleiding Als je leert programmeren lijkt het nogal overweldigend om die eerste stappen te doorworstelen. Er zijn dan ook heel wat programmeertalen (Java, Ruby, Python, Perl,
VAN HET PROGRAMMEREN. Inleiding
OVERZICHT VAN HET PROGRAMMEREN Inleiding Als je leert programmeren lijkt het nogal overweldigend om die eerste stappen te doorworstelen. Er zijn dan ook heel wat programmeertalen (Java, Ruby, Python, Perl,
Computervaardigheden. Universiteit Antwerpen. Computervaardigheden en Programmatie. Grafieken en Rapporten 1. Inhoud. Wat is scripting?
Inhoud Computervaardigheden Hoofdstuk 4 Scripting (Let op: dit is enkel voor studenten Biologie.) Dit hoofdstuk bekijkt heel kort de basis van scripting. - Opstellen van functies. - Conditionele code.
Programmeren met Arduino-software
Programmeren met Arduino-software De software waarin we programmeren is Arduino IDE. Deze software is te downloaden via www.arduino.cc. De programmeertaal die hier gebruikt wordt, is gebaseerd op C en
Deel 1: Arduino kennismaking. Wat is een microcontroller, structuur van een programma, syntax,
Deel 1: Arduino kennismaking Wat is een microcontroller, structuur van een programma, syntax, Wat is een microcontroller Wat is een microcontroller? Microcontroller = kleine dedicated computer. - Beperkt
[13] Rondjes draaien (loops)
[13] Rondjes draaien (loops) Met de if else uit de leerfiche [11] hebben we leren werken met één van de belangrijkste programmeerstructuren in Python. Bijna even belangrijk zijn de verschillende mogelijkheden
Zelftest Inleiding Programmeren
Zelftest Inleiding Programmeren Document: n0824test.fm 22/01/2013 ABIS Training & Consulting P.O. Box 220 B-3000 Leuven Belgium TRAINING & CONSULTING INLEIDING BIJ DE ZELFTEST INLEIDING PROGRAMMEREN Deze
Een spoedcursus python
Een spoedcursus python Zoals je in de titel misschien al gezien hebt, geven wij een spoedcursus Python. Door deze cursus leer je alle basics, zoals het rekenen met Python en het gebruik van strings. Het
BEGINNER JAVA Inhoudsopgave
Inhoudsopgave 6 Configuratie Hallo wereld! Praten met de gebruiker Munt opgooien Voorwaarden Lussen......6 Configuratie Met deze Sushi kaarten ga je een simpel spel maken met één van de meest populaire
Programmeren en Wetenschappelijk Rekenen in Python. Wi1205AE I.A.M. Goddijn, Faculteit EWI 22 april 2014
Programmeren en Wetenschappelijk Rekenen in Python Wi1205AE, 22 april 2014 Inleiding Cursus coördinator e-mail Docent e-mail : Jacco Hoekstra : [email protected] : Ingeborg Goddijn : [email protected]
Small Basic Programmeren Text Console 2
Oefening 1: Hoogste getal Je leest een reeks positieve gehele getallen in totdat je het getal 0 (nul) invoert. Daarna stopt de invoer en druk je een regel af met het hoogste getal uit de reeks. Voorbeeld:
Programmeermethoden NA. Week 3: Controlestructuren
Programmeermethoden NA Week 3: Controlestructuren Kristian Rietveld http://liacs.leidenuniv.nl/~rietveldkfd/courses/prna/ Bij ons leer je de wereld kennen 1 Inleveren opdracht 1 Lever digitaal sxxxxxxx-syyyyyyy-opdr1.py
Je gaat leren programmeren en een spel bouwen met de programmeertaal Python. Websites zoals YouTube en Instagram zijn gebouwd met Python.
1 Je gaat leren programmeren en een spel bouwen met de programmeertaal Python. Websites zoals YouTube en Instagram zijn gebouwd met Python. Voordat je leert programmeren, moet je jouw pc zo instellen dat
Een computerprogramma is opgebouwd uit een aantal instructies die op elkaar volgen en die normaal na elkaar uitgevoerd worden.
2 Programmeren 2.1 Computerprogramma s Een computerprogramma is opgebouwd uit een aantal instructies die op elkaar volgen en die normaal na elkaar uitgevoerd worden. (=sequentie) Niet alle instructies
Syntax- (compile), runtime- en logische fouten Binaire operatoren
Inhoud Syntax- (compile), runtime- en logische fouten Binaire operatoren Operaties op numerieke datatypen Evaluatie van expressies, bindingssterkte Assignment operaties en short-cut operatoren Controle
Programmeermethoden NA. Week 5: Functies (vervolg)
Programmeermethoden NA Week 5: Functies (vervolg) Kristian Rietveld http://liacs.leidenuniv.nl/~rietveldkfd/courses/prna2016/ Functies Vorige week bekeken we functies: def bereken(a, x): return a * (x
VBA voor Doe het Zelvers deel 20
VBA voor Doe het Zelvers deel 20 Handleiding van Auteur: leofact Augustus 2015 handleiding: VBA voor Doe het Zelvers deel 20 Vorige aflevering In het vorige deel werd besproken hoe je de structuur en vensteropbouw
Groepen, ringen en velden
Groepen, ringen en velden Groep Een groep G is een verzameling van elementen en een binaire operator met volgende eigenschappen: 1. closure (gesloten): als a en b tot G behoren, doet a b dat ook. 2. associativiteit:
Datastructuren Programmeeropdracht 3: Expressies. 1 Expressies. Deadline. Dinsdag 8 december 23:59.
Datastructuren 2015 Programmeeropdracht 3: Expressies Deadline. Dinsdag 8 december 23:59. Inleiding. Deze opdracht is losjes gebaseerd op Opdracht 5.13.2 in het boek van Drozdek. U wordt gevraagd expressies
PSD. Reeksen van logische procedures om problemen op te lossen in een eindig aantal stappen.
Inleiding Computers en andere digitale apparatuur is tegenwoordig niet meer weg te denken in de huidige samenleving. Zonder programma s zijn deze apparaten echter niets waard. Het zijn de programma s die
maplev 2010/7/12 14:02 page 15 #17 Nadere detaillering van een aantal zaken van Module 1 Geen,, " ", \, save, read, protect, unprotect
maplev 2010/7/12 14:02 page 15 #17 Module 2 Het gebruik van Maple, vervolg Onderwerp Voorkennis Expressies Nadere detaillering van een aantal zaken van Module 1 Geen,, " ", \, save, read, protect, unprotect
Zoemzinnen. Algemene info. Functies met een variabel aantal argumenten
Zoemzinnen Functies met een variabel aantal argumenten Bij het definiëren van een functie leg je in principe vast hoeveel argumenten er aan de functie moeten doorgegeven worden. Dit aantal correspondeert
OPDRACHT Opdracht 2.1 Beschrijf in eigen woorden wat het bovenstaande PSD doet.
Les C-02: Werken met Programma Structuur Diagrammen 2.0 Inleiding In deze lesbrief bekijken we een methode om een algoritme zodanig structuur te geven dat er gemakkelijk programmacode bij te schrijven
1 Rekenen in eindige precisie
Rekenen in eindige precisie Een computer rekent per definitie met een eindige deelverzameling van getallen. In dit hoofdstuk bekijken we hoe dit binnen een computer is ingericht, en wat daarvan de gevolgen
II. ZELFGEDEFINIEERDE FUNCTIES
II. ZELFGEDEFINIEERDE FUNCTIES In Excel bestaat reeds een uitgebreide reeks van functies zoals SOM, GEMIDDELDE, AFRONDEN, NU enz. Het is de bedoeling om functies aan deze lijst toe te voegen door in Visual
Practicum Programmeerprincipes
REEKS 3 Practicum Programmeerprincipes 2009-2010 [email protected] WERKEN MET FUNCTIES IN PICO Functies, controlestructuren, recursie, iteratie, blokstructuren en functionele parameters in Pico. Het woordenboek
Hoofdstuk 0. Van Python tot Java.
Hoofdstuk 0. Van Python tot Java. In dit eerste hoofdstuk maken we de overstap van Python naar Java. We bespreken de verschillen en geven wat achtergrondinformatie. In het volgende hoofdstuk gaan we dieper
Programmeren. a. 0, 0, 0 b. 0, 0, 27 c. 15, 12, 0 d. 15, 12, 27
Programmeren 0. (1 punt.) Stel, een "afhankelijk kind" is een persoon is die jonger is dan 18 jaar, en hooguit 8.000 euro verdient. Welke van de onderstaande expressies definieert een afhankelijk kind?
Info-books. Toegepaste Informatica. Deel 20 : Algoritmen en programmeren in Access en Excel (Basis) AL20. Jos Gils Erik Goossens
Info-books AL20 Toegepaste Informatica Deel 20 : Algoritmen en programmeren in Access en Excel (Basis) Jos Gils Erik Goossens Hoofdstuk 6 Lusstructuren of iteraties 6.1 Probleemstelling Het gebeurt dikwijls
RAAD HET GETAL. Hoofdstuk 4. Het spelletje 'Raad het getal' Voorbeeld van uitvoering van 'Raad het getal' Hoofdstuk 4 Raad het getal 21
Hoofdstuk 4 Raad het getal 21 Hoofdstuk 4 RAAD HET GETAL In dit hoofdstuk behandelen we: import-statements Modules Argumenten while-statements Voorwaarden Blokken Boole-waarden Vergelijkingsoperatoren
Week 2 : Hoofdstukken 2 en 6; extra stof: inleiding pointers
Week 2 : Hoofdstukken 2 en 6; extra stof: inleiding pointers Hoofdstuk 6: Beslissingen: if-statement en switch-statement. Inleiding: Condities zijn waar (true) of onwaar (false) In C staat het int-getal
Uitleg: In de bovenstaande oefening zie je in het eerste blokje een LEES en een SCHRIJF opdracht. Dit is nog lesstof uit het tweede trimester.
In onderstaande oefeningen zijn kleuren gebruikt. Deze dienen aleen om de structuren makkelijker terug te kunnen herkennen. Ze worden niet standaard zo gebruikt. De dunne rood/roze balken zijn ook geen
Programmeren in Java les 3
4 september 2015 Deze les korte herhaling vorige week loops methodes Variabelen Soorten variabelen in Java: integer: een geheel getal, bijv. 1,2,3,4 float: een gebroken getal, bijv. 3.1415 double: een
Korte handleiding Maple, bestemd voor gebruik bij de cursus Wiskunde
Korte handleiding Maple, bestemd voor gebruik bij de cursus Wiskunde voor B. 1 Eenvoudige operaties en functies. 1. De bewerkingen optellen aftrekken, vermenigvuldigen, delen en machtsverheffen worden
SEQUENTIE-STRUCTUUR. Oefening: Dichtheid
SEQUETIE-STRUCTUUR Oefening: Dichtheid geef diameter vd bol(m) //Declaratie input variabelen double diameter; double soortmassa; //Declaratie variabelen voor tussenresultaten double volume; diameter //Declaratie
GEDETAILLEERDE INHOUD
GEDETAILLEERDE INHOUD dankwoord 17 Inleiding 19 Waarom leer je programmeren?... 19 Waarom Python?... 20 Waarom Minecraft?... 20 Wat staat er in dit boek?.... 20 Online bronnen... 22 Ga nu maar op avontuur...
6. Functies. 6.1. Definities en gebruik van functies/variabelen
Computeralgebra met Maxima 6. Functies 6.1. Definities en gebruik van functies/variabelen Een van de belangrijkste gereedschappen in een CAS betreft het gebruik van functies (definitie, berekening en grafiek).
DEC SDR DSP project 2017 (2)
DEC SDR DSP project 2017 (2) Inhoud: DSP software en rekenen Effect van type getallen (integer, float) Fundamenten onder DSP Lezen van eenvoudige DSP formules x[n] Lineariteit ( x functie y dus k maal
Een topprogrammeur in het OO programmeren is Graig Larman. Hij bedacht de volgende zin:
Java Les 2 Theorie Beslissingen Algemeen Net als in het dagelijks leven worden in software programma s beslissingen genomen, naast het toekennen van waarden aan variabelen zijn beslissingen één van de
Je gaat leren programmeren in Ruby. En daarna in Ruby een spelletje maken. Websites zoals Twitch en Twitter gemaakt zijn met behulp van Ruby?
1 Je gaat leren programmeren in Ruby. En daarna in Ruby een spelletje maken. Websites zoals Twitch en Twitter gemaakt zijn met behulp van Ruby? Voordat je begint met programmeren, moet je Ruby installeren.
Korte handleiding Maple bij de cursus Meetkunde voor B
Korte handleiding Maple bij de cursus Meetkunde voor B Deze handleiding sluit aan op en is gedeeltelijk gelijk aan de handleidingen die gebruikt worden bij de cursussen Wiskunde 2 en 3 voor B. Er zijn
DE ASTRO PI PROGRAMMEREN VOOR MISSION ZERO
DE ASTRO PI PROGRAMMEREN DOCENTENHANDLEIDING 1 Deze handleiding is bedoeld om leerlingen te ondersteunen bij de Astro Pi Challenge, waarbij leerlingen een programma voor de Astro Pi-computer in het ISS
Een typisch programma in C en C++ bestaat uit een aantal onderdelen:
Eerste stappen in C. Een typisch programma in C en C++ bestaat uit een aantal onderdelen: /* Alles wat op meerdere lijnen staat zoals hier is commentaar. */ // Dit is commentaar op 1 lijn. Geldig tot einde
1 Rekenen met gehele getallen
1 Inhoudsopgave 1 Rekenen met gehele getallen... 1.1 De gehele getallen... 1. Optellen... 1. Opgaven... 1. Aftrekken... 1. Opgaven... 1. Vermenigvuldigen... 1. Opgaven... 1.8 Delen... 9 1.9 Opgaven...9
Een eenvoudig algoritme om permutaties te genereren
Een eenvoudig algoritme om permutaties te genereren Daniel von Asmuth Inleiding Er zijn in de vakliteratuur verschillende manieren beschreven om alle permutaties van een verzameling te generen. De methoden
UNIVERSITEIT ANTWERPEN FACULTEIT WETENSCHAPPEN DEPARTEMENT WISKUNDE-INFORMATICA OBERON CODE CONVENTIONS
UNIVERSITEIT ANTWERPEN FACULTEIT WETENSCHAPPEN DEPARTEMENT WISKUNDE-INFORMATICA OBERON CODE CONVENTIONS Laatste aanpassing: 15 oktober 2003 Inhoudsopgave 1 Bestandsnamen 3 2 Organizatie Bestanden 3 3 Indentatie
16.0 Voorkennis. Voorbeeld 1: Los op in 2x + 3i = 5x + 6i -3x = 3i x = -i
16.0 Voorkennis Voorbeeld 1: Los op in 2x + 3i = 5x + 6i -3x = 3i x = -i Voorbeeld 2: Los op in 4x 2 + 12x + 15 = 0 4x 2 + 12x + 9 + 6 = 0 (2x + 3) 2 + 6 = 0 (2x + 3) 2 = -6 (2x + 3) 2 = 6i 2 2x + 3 =
Proefexemplaar. Wendy Luyckx Mark Verbelen Els Sas. Dirk Vandamme. bewerkt voor het GO! onderwijs van de Vlaamse Gemeenschap door. Cartoons.
bewerkt voor het GO! onderwijs van de Vlaamse Gemeenschap door Wendy Luyckx Mark Verbelen Els Sas Cartoons Dirk Vandamme Leerboek Getallen ISBN: 78 0 4860 48 8 Kon. Bib.: D/00/047/4 Bestelnr.: 4 0 000
10.0 Voorkennis. cos( ) = -cos( ) = -½ 3. [cos is x-coördinaat] sin( ) = -sin( ) = -½ 3. [sin is y-coördinaat] Willem-Jan van der Zanden
10.0 Voorkennis 5 1 6 6 cos( ) = -cos( ) = -½ 3 [cos is x-coördinaat] 5 1 3 3 sin( ) = -sin( ) = -½ 3 [sin is y-coördinaat] 1 Voorbeeld 1: Getekend is de lijn k: y = ½x 1. De richtingshoek α van de lijn
Het installatiepakket haal je af van de website http://www.gedesasoft.be/.
Softmaths 1 Softmaths Het installatiepakket haal je af van de website http://www.gedesasoft.be/. De code kan je bekomen op de school. Goniometrie en driehoeken Oplossen van driehoeken - Start van het programma:
Programmeren A. Genetisch Programma voor het Partitie Probleem. begeleiding:
Programmeren A Genetisch Programma voor het Partitie Probleem begeleiding: Inleiding Het Partitie Probleem luidt als volgt: Gegeven een verzameling van n positieve integers, vindt twee disjuncte deelverzamelingen
Matlab introductie. Kees Vuik
Matlab introductie Kees Vuik 2014 Delft University of Technology Faculty of Electrical Engineering, Mathematics and Computer Science Delft Institute of Applied Mathematics Copyright 2014 by Delft Institute
Algemeen. Rorschachtest. Algemene info
Algemeen Als Python de volgende regel moet lezen uit een tekstbestand, dan wordt er gelezen tot en met de eerstvolgende newline ('\n') of tot het einde van het bestand. Het laatste karakter van de regel
2 n 1. OPGAVEN 1 Hoeveel cijfers heeft het grootste bekende Mersenne-priemgetal? Met dit getal vult men 320 krantenpagina s.
Hoofdstuk 1 Getallenleer 1.1 Priemgetallen 1.1.1 Definitie en eigenschappen Een priemgetal is een natuurlijk getal groter dan 1 dat slechts deelbaar is door 1 en door zichzelf. Om technische redenen wordt
Uitwerking tentamen Analyse van Algoritmen, 29 januari
Uitwerking tentamen Analyse van Algoritmen, 29 januari 2007. (a) De buitenste for-lus kent N = 5 iteraties. Na iedere iteratie ziet de rij getallen er als volgt uit: i rij na i e iteratie 2 5 4 6 2 2 4
Bijlage 11 - Toetsenmateriaal
Bijlage - Toetsenmateriaal Toets Module In de eerste module worden de getallen behandeld: - Natuurlijke getallen en talstelsels - Gemiddelde - mediaan - Getallenas en assenstelsel - Gehele getallen met
Leren Programmeren met Visual Basic 6.0 Les 3+4. Hoofdstuk 4 : De Selectie
Leren Programmeren met Visual Basic 6.0 Les 3+4 Hoofdstuk 4 : De Selectie Visual Basic 6.0 1 Basisstructuren (herhaling) Sequentie (HK2) : Alle opdrachten gewoon na mekaar uitvoeren. Hier worden geen keuzes
TELEPORTEREN MET VARIABELEN
2 TELEPORTEREN MET VARIABELEN Ben je zover dat je de kracht van Python kunt gebruiken om jouw Minecraft wereld te beheersen? In dit hoofdstuk krijg je een korte rondleiding langs de basisbegrippen van
Het warmteverlies van het lichaamsoppervlak aan de wordt gegeven door de volgende formule:
Opgave 1. (4 punten) Inleiding: Een vleermuis is een warmbloedig zoogdier. Dat wil zeggen dat hij zijn lichaamstemperatuur op een konstante waarde moet zien te houden. Als de omgeving kouder is dan de
Modelleren en Programmeren
Modelleren en Programmeren Jeroen Bransen 13 november 2015 Expressies Functies Ingebouwde functies Variabelenbereik Inleveropgave 1 Terugblik Programma is een lijst van opdrachten Terugblik Programma is
Opgaven. Python Assessment
Opgaven Python Assessment Nijmegen - Utrecht www.atcomputing.nl Copyright 2015,2016 Versie: 1a Inleiding Met dit assessment kun je controleren of je voldoende parate kennis over Python hebt om te beginnen
Rekenen aan wortels Werkblad =
Rekenen aan wortels Werkblad 546121 = Vooraf De vragen en opdrachten in dit werkblad die vooraf gegaan worden door, moeten schriftelijk worden beantwoord. Daarbij moet altijd duidelijk zijn hoe de antwoorden
Inleiding Programmeren 2
Inleiding Programmeren 2 Gertjan van Noord November 26, 2018 Stof week 3 nogmaals Zelle hoofdstuk 8 en recursie Brookshear hoofdstuk 5: Algoritmes Datastructuren: tuples Een geheel andere manier om te
Getallenleer Inleiding op codeertheorie. Cursus voor de vrije ruimte
Getallenleer Inleiding op codeertheorie Liliane Van Maldeghem Hendrik Van Maldeghem Cursus voor de vrije ruimte 2 Hoofdstuk 1 Getallenleer 1.1 Priemgetallen 1.1.1 Definitie en eigenschappen Een priemgetal
WORKSHOP ORANGE PI & PYTHON v september 2017
WORKSHOP ORANGE PI & PYTHON v1.1 21 september 2017 In deze workshop maak je kennis met een zogenaamde bord-computer ter grootte van een bankpas. Een bord-computer kan gebruikt worden als een normale computer
Voorbeelden. Sorteren. Voorbeeld: n = 5. # intsort.py: sorteren van een rij getallen
Voorbeelden Sorteren Schrijf een programma dat een rij gehele getallen sorteert een eerste functie leest de rij gehele getallen; een tweede functie sorteert deze getallenrij van klein naar groot; een derde
Module 3: Scratch programmeren: is het logisch of is het niet logisch?
Module 3: Scratch programmeren: is het logisch of is het niet logisch? Inhoudsopgave Module 3: Scratch programmeren: is het logisch of is het niet logisch?...1 Wat is een computerprogramma eigenlijk?...2
1.0 Voorkennis. Voorbeeld 1: Los op: 6x + 28 = 30 10x.
1.0 Voorkennis Voorbeeld 1: Los op: 6x + 28 = 30 10x. 6x + 28 = 30 10x +10x +10x 16x + 28 = 30-28 -28 16x = 2 :16 :16 x = 2 1 16 8 Stappenplan: 1) Zorg dat alles met x links van het = teken komt te staan;
Functioneel programmeren
Functioneel programmeren Practicumopgave 2: Mastermind Het doel van deze opgave is het implementeren van het spel Mastermind; zie http://nl.wikipedia.org/wiki/mastermind voor een uitleg. Het spel is klein
Derive in ons wiskundeonderwijs Christine Decraemer
Dag van de Wiskunde 003 de en 3 de graad Module 6: Eerste sessie Derive in ons wiskundeonderwijs Christine Decraemer Je kunt Derive het best vergelijken met een uitgebreid rekentoestel. Niet enkel numerieke,
Zomercursus Wiskunde. Module 1 Algebraïsch rekenen (versie 22 augustus 2011)
Katholieke Universiteit Leuven September 011 Module 1 Algebraïsch rekenen (versie augustus 011) Inhoudsopgave 1 Rekenen met haakjes 1.1 Uitwerken van haakjes en ontbinden in factoren............. 1. De
Inleiding Programmeren 2
Inleiding Programmeren 2 Gertjan van Noord November 28, 2016 Stof week 3 nogmaals Zelle hoofdstuk 8 en recursie Brookshear hoofdstuk 5: Algoritmes Datastructuren: tuples Een geheel andere manier om te
Opgave 1. (4 punten) Inleiding: Vraag: Hints: (maximaal 2 bonuspunten) Tentamen Algoritmiek voor Biologen
Opgave 1. (4 punten) Elk jaar verliest een boom al z'n bladeren. Een boom begint op dag D met B bladeren. Op de eerste dag is voor elk blad dat aan de boom zit de kans op afvallen 0.03. Voor elke volgende
slides12.pdf December 14, 2001 1
Onderwerpen Inleiding Algemeen 12 Getallen Getallen Representaties Rekenen Problemen Piet van Oostrum 12 dec 2001 INL/Alg-12 1 X INL/Alg-12 1 X Getallen Soorten getallen Wat is een getal? Experiment: met
