Tot het stilstaat
In de vorige stap mat je hoeveel de verdeling in één dag verandert. Nu laat je
de computer doorrekenen tot geen enkele kans nog 0,001 of meer verandert.
Hoeveel dagen dat duurt, weet je vooraf niet, en daarom gebruik je een while. Bij
PageRank deed je dat in
itereren tot het stabiel is,
en CS50 vraagt dezelfde grens van 0,001.
while ken je uit De while-loop.
Voorspel
verschil = 1
rondes = 0
while verschil >= 0.001:
verschil = verschil / 2
rondes = rondes + 1
print(rondes)
Wat print dit?
Antwoord
10
Na tien keer halveren is verschil 0.0009765625, kleiner dan 0,001. Begin je
met verschil = 0, dan print hij 0: de voorwaarde is meteen niet waar, en de
loop draait geen enkele keer.
Zo werkt het
De while rekent door zolang verschil nog 0,001 of meer is. Zet verschil
vóór de loop op 1, anders begint de loop niet eens. Bij het weer reken je in
de loop eerst nieuw uit, dan het verschil met verdeling, en pas daarna zet
je verdeling = nieuw. Andersom vergelijk je de nieuwe verdeling met
zichzelf.
Stopt je while nooit, dan loopt het tabblad vast: de speeltuin heeft geen
stopknop. Kopieer je code daarom eerst naar een kladblok voordat je op Voer
uit drukt.
Opdracht: tot het stilstaat
Reken de verdeling door tot hij stilstaat, en print hoeveel dagen dat duurde:
6 dagen
zon 0.338
wolken 0.366
regen 0.296
Begin klein, en breid de code stap voor stap uit:
- Draai de code: hij rekent één dag uit, en print het verschil met vandaag: 0.5.
- Zet
verschil = 1boven de berekening, en zet alles vanafnieuw = {}in eenwhile verschil >= 0.001:. Zet aan het eind van de loopverdeling = nieuw. Hij print nu elke dag een kleiner verschil. - Tel de dagen in
dagen, en print na de loop het aantal dagen en de verdeling, afgerond op drie cijfers.
Tip
Stopt hij na één dag? Kijk wat verschil is als de while voor de tweede
keer kijkt. Staat verschil = 0 ín de loop, vóór de for weer in nieuw:?
Antwoord
Dit vervangt alles vanaf nieuw = {} in de editor:
verschil = 1
dagen = 0
while verschil >= 0.001:
nieuw = {}
for morgen in model:
kans = 0
for vandaag in model:
kans = kans + verdeling[vandaag] * model[vandaag][morgen]
nieuw[morgen] = kans
verschil = 0
for weer in nieuw:
verschil = max(verschil, abs(nieuw[weer] - verdeling[weer]))
verdeling = nieuw
dagen = dagen + 1
print(dagen, "dagen")
for weer in verdeling:
print(weer, round(verdeling[weer], 3))
6 dagen
zon 0.338
wolken 0.366
regen 0.296
Dit zijn dezelfde getallen als na zes dagen in dag na dag, maar nu weet de computer zelf wanneer hij kan stoppen.
Er gaat iets mis
Wat je ziet: de loop stopt al na één dag, met een verdeling die nog lang niet stilstaat.
Oorzaak: je begon de nieuwe verdeling met nieuw = verdeling in plaats
van nieuw = {}. Dat maakt geen kopie, maar een tweede naam voor dezelfde
dictionary. Verander je nieuw, dan verandert verdeling mee, en is het
verschil tussen de twee altijd 0.
Oplossing: begin elke dag met een lege nieuw = {}. Wil je toch met een
kopie beginnen, maak hem dan met .copy().
# FOUT
verdeling = {"zon": 1, "regen": 0}
nieuw = verdeling
nieuw["zon"] = 0.5
print(verdeling["zon"]) # 0.5
# GOED
verdeling = {"zon": 1, "regen": 0}
nieuw = verdeling.copy()
nieuw["zon"] = 0.5
print(verdeling["zon"]) # 1
Door naar een set van links.