Yksikkömurtolukujen desimaalikehitelmien jakson pituuksista 2 – jakson pituus Pythonilla

[edit. 29.9. Lisäsin while-silmukan koodin loppuun]

Selvitän tässä miten Python koodini toimii. Sen avulla voi laskea yksikkömurtolukujen jaksojen pituuksia. Esitän alussa miten käytin GeoGebraa koodaamisen apuna. Tein tämän koodinpätkän sekä for-silmukall että while-silmukalla.

Jakokulma

Minä kun olen sen verran kokenut, niin olen oppinut perinteisen jakokulman jo kansa- tai ainakin keskikoulussa. Jakokulmassa näki jaksollisuuden, kun jakojäännös toistui. Alla olevassa taulukossa solussa B1 on murtoluvun 1/7 osoittaja (murtoviivan yläpuolella oleva luku)  ja C1 nimittäjä (se alapuoli). Solussa B2 on kokonaisosa ensimmäisestä jakolaskusta, solussa C2 ensimmäisen jakolaskun jakojäännös. Niiden alapuolella kokonaisosa 10* edellisestä kokonaisosasta ja jakojäännös. 

Kun loin tämän esimerkin, niin käytin englanninkielisiä komentoja Div ja Mod, ne kun ovat lyhyempiä kirjoittaa.  GeoGebrassa voi kirjoittaa suomenkielisessäkin versiossa englannikielisiä komentoja, toki ohjelma kääntää komennon suomenkielelle.

Alla on ½.

Seuraavassa kuvassa on ⅓.

Alla on tuotettu 1/7 = 0.142857142857… Kun tuota jaksoa tutkii, niin silloin saattaa nähdä, että jakso alkaa toistua, kun C-sarakkeelle eli jakojäännökseen tulee sama luku. Mikäli jakojäännökseen tulee nolla, niin desimaali on päättyvä. Niinpä eri vaihtoehtoja jakojäännökselle on vai nimittäjä – 1:n verran. Näin ollen luvun 1/n pisin mahdollinen jakso on 1 – n. Palaan tulevaisuudessa näihin syklisiin lukuihin. Ne ovat tällä hetkellä päällimmäisenä mielessäni.

Oheinen taulukko antaa aika hyvän mallin, miten selvittää jakson pituus. Pieni ongelma tulee desimaalin alussa olevien nollien kanssa. Esimerkiksi 1/35 = 0.0285714285714… Tässä jakso alkaa vasta kun jakojäännös 10 toistuu; ensimmäinen jakojäännösykkönen ei esiinny jakojäännöksissä ensiesiintymisensä jälkeen.

Tämän ongelman saa ratkaistua esimerkiksi kertomalla osoittaja kymmenellä, sadalla, … siten että kolmannella rivillä ei ole nollaa. Alla olevassa kuvassa solussa B2 on 

=10^ceil(lg(C1))

Huomaa, että Pythonkoodissani en käytä logaritmia, sillä sen käyttö voi aiheuttaa pyöristysvirheitä isojen lukujen yhteydessä. Vähennän yhden nollan osoittajasta, se yksinkertaistaa algoritmiani.

Kun aloin koodaamaan tätä GeoGebralla, päädyin aika pitkiin komentoriveihin, en pystynyt enää hahmottamaan virheitä, niinpä luovutin. Saatan palata tähän mikäli saan kirkastettua algoritmini mielessäni GeoGebraan sopivaksi.

python koodi

Tutkin tässä vain jakson pituuksia, jätän yksinkertaisuuden vuoksi desimaalien jakson tuonnemmaksi. Pythonissa // laskee jakolaskun kokonaisosan ja % jakojäännöksen. Laitan koodiin print-funktioita, jotta koodin etenemistä voi seurata helpommin. Tämä olisi voinut olla hieman yksinkertaisempi while-silmukalla, päätin tehdä tämän kuitenkin for-silmukalla.

Pythonilla jakson pituuden etsiminen on suhteellisen suoraviivaista, käytän ensimmäisessä esimerkissä nimittäjän arvoa 6 rivillä 1.

Rivillä 3 lasketaan ensin  nimittäjän numeroiden lukumäärä, str() muuttaa luvun 6 merkkijonoksi ”6” ja len() laskee sen pituuden. Lopulta ensimmäiseksi osoittajaksi määritellään 10^(numeroiden lukumäärä – 1). Kuutosen tapauksessa se on 10^0 = 1. Ideana on saada osoittajaan sellainen kymmenen potenssi, että siinä on yhtä monta nollaa kuin nimittäjässä on numeroita.

Rivillä 6 on ensimmäinen jakojäännös, eli tässä tapauksessa 1//6 = 1 ja rivillä 7 luodaan jakojäännöksien lista ja lisätään sinne ensimmäinen jakojäännös eli tässä tapauksessa ykkönen.

For-silmukassa rivillä tulostetaan seuraavan jakolaskun osoittaja ja nimittäjä, ensimmäisellä kierroksella 10 ja 6.

Rivillä 12 lasketaan uusi jakojäännös esimerkkitapauksessa (10*1)//6 = 10//6 = 4.

Riveillä 14 – 17 tutkitaan onko jakojäännös nolla. Mikäli se on, niin koko for-silmukka lopetetaan break-rivillä, ja samalla tiedetään, että kyseessä on päättyvä desimaalikehitelmä.

Riveillä 16-21 elifin avulla selvitetään onko  jakojäännös jaannokset listassa, ensimmäisellä kierroksella se ei ole sillä listassa [1] ei ole nelosta.

Riveillä 22 – 23 lisätään jakojäännös jaannokset-listaan, mikäli edelliset ehdot eivät ole voimassa. Tässä vaiheessa 4 lisätään jaannokset-listaan. Jakojäännöslista on nyt [1, 4]

Seuraavassa for-silmukassa jakojäännös on 40//6 = 4 eli rivi 18 elif-ehto on voimassa. Jakson pituudeksi saadaan jaannokset-listan pituus  – se paikka (Pythonin logiikalla) missä luku 4 on eli 2 – 1 = 1.

Muutamia esimerkkejä koodista. Tässä nimittäjä on 2.

Nimittäjän arvolla 7 saadaan pidempi jakso.

13

666

Tätä kirjoittaessani tajusin, että ensimmäinen jakojäännös on tietysti aina tuon ensimmäinen kymmenen potenssi eli 10**(len(str(nimittaja))-1).

python ohjelma

Siistin koodia ja teen python funktion, joka tulostaa jakson pituuden. Tuotan listan, jossa on vaikkapa 50 ensimmäisen yksikkömurtoluvun jaksojen pituudet. Samalla laitan jaksojen pituudet kuvaajaan.

100 ensimmäistä: [0, 0, 1, 0, 0, 1, 6, 0, 1, 0, 2, 1, 6, 6, 1, 0, 16, 1, 18, 0, 6, 2, 22, 1, 0, 6, 3, 6, 28, 1, 15, 0, 2, 16, 6, 1, 3, 18, 6, 0, 5, 6, 21, 2, 1, 22, 46, 1, 42, 0]

Python koodi löytyy Colabista https://colab.research.google.com/drive/1PzbK6xjohZq5KS80DHMqYREZ1cC0cGXR?usp=sharing

tarkistus

Pieni pelko tällaisen laskennan tuottamisessa on, että koodi laskee väärin. Edellisessä tarinassani kerroin T.D. Doen sivusta, jossa on lueteltu 10000 ensimmäisen yksikkömurtoluvun jaksojen pituudet. Loin luvuista listan nimeltä oikeat. Vaikuttaa siltä, että koodini laskee oikein.

Noiden 10000 luvun tuottamiseen kului Google Colabissa reilut 4 minuuttia. 20000 jakson pituuden laskemiseen kului noin 31 min. Vaikuttaa siltä, että laskenta-ajan kasvu on tyyppiä n^3.

while-silmukka

Koodin idea on lähes sama kuin edellisen luvun for-silmukassakin. Tämäkin koodi laskee jakson pituuden ja käyttää sitä apuna kun lopullinen jaksolista tuotetaan.

Oheinen jakso-funktio tulostaa yksikkömurtoluvun 1/n desimaalikehitelmän jakson listana ja jakson pituuden. Poiketen for-silmukka-koodista, niin aloitan desimaalien keräämisen suoraan 1//n:n jakamisella rivillä 2. Rivin 6 while-silmukka pyörii niin kauan kuin jakojäännöstä ei ole jaannokset-listassa. 

Kun jakojäännös on jakojäännöslistassa, niin rivillä 11 päätellään jakson pituus. Lisäksi riveillä 12-14 muutetaan tuloste, jos jakojäännös on nolla. Lopulta rivillä 15 määritetään jaksolliset desimaalit ja jakson pituus.

Riveillä 21-24 tuotetaan 100 ensimmäistä jaksoa ja niiden pituudet listaksi.

Ajallisesti tämä koodi vaikuttaa yhtä vikkelältä kuin for-silmukkakin. 10000 jakson tuottamisen Colabissa kului reilut 4 min.

Nyt kun minulla on helppo tapa tuottaa jakson pituuksia ja itse jaksoja, voin tulevissa tarinoissa keskittyä matematiikkaan.


lähteet

Edellinen artikkelini aiheesta
https://mikkorahikka.blog/2022/09/20/yksikkomurtolukujen-desimaalikehitelmien-jakson-pituuksista-1-pohdittavaa-ongelmia/

Koodi löytyy Colabissa
https://colab.research.google.com/drive/1PzbK6xjohZq5KS80DHMqYREZ1cC0cGXR?usp=sharing

Repeating decimal Wikipediassa
https://en.wikipedia.org/wiki/Repeating_decimal

Cyclic number MathWorldissa
https://mathworld.wolfram.com/CyclicNumber.html

Uusi parempi turtle-kirjasto Colabin Pythoniin

Colab on Googlen tuottama ohjelmointiympäristö Python-kielen opiskelun avuksi. Aiemmin julkaistu Colabin kilpikonnagrafiikka-kirjasto (ColabTurtle) oli hieman puutteellinen, koska se ei toiminut kuten perinteiset Logo/Python-turtlet. ColabTurtlePlus on uusi kirjasto, sen toiminta vastaa ”virallista” Pythonin Turtle-kirjastoa, joka toimii vaikkapa Idlessä ja Replissä (https://replit.com/ ). Ymmärtämykseni mukaan joissakin yläasteen matikan kirjoissakin käytetyt PythonTurtlekoodipätkät toimivat ColabTurtlePlussassa.

Minä ainakin olen melkoisen innostunut ColabTurtlePlussasta, koordinaatiston origo on keskellä näyttöä ja xy-koordinaatisto toimii ”oikein”. Uskoisin, että tästä on apua opettajille/oppilaille, jotka käyttävät kilpikonnagrafiikkaa Pythonin oppimiseen. Minä aloitin kilpikonnalla koodaamisen opiskelun Logolla ja kilpikonnagrafiikalla noin vuonna 1983, kun olin auskultoimassa Helsingin yliopistossa. Jotenkin tämä liittyi konstruktivismiin :o)

Katso Colabiin liittyviä artikkeleita blogissani https://mikkorahikka.blog/?s=colab

Näytän pari esimerkkiä aiheeseen liittyen kuvankaappauksineen. Googlen Colaborary löytyy osoitteesta https://colab.research.google.com/ jos olet aloitelija, niin katso sivulta ohjeita. Käytän tässä pelkästään koodisoluja, esimerkkisivulla on mukana myös tekstisoluja. En laita koodin sekaan #kommentteja.

Koodi löytyy täältä https://colab.research.google.com/drive/1B3DJRc0RA7jY5Wci53h6OSB7AKuy45u1?usp=sharing

ColabTurtlePlus

Rivillä 1 asennetaan kirjasto Colabiin ja rivillä 2 luetaan se käyttöön. Nämä pitää olla suoritettuna ennen kuin konnaa voi käyttää Colab-sivulla.

Kun kaikki toimii, niin selaimessa (minulla Chrome) näkyy tällainen tuotos.

Piirretään konnalla neliö. Tätä kirjoittaessa en tajua, miksi tuonne koodirivien alapuolelle tulevat nuo aaltoviivat, liittynee Chromen asetuksiini, en tee siitä ongelmaa.

Rivillä 3 konna kulkee eteenpäin 200 askelta ja rivillä  4 se kääntyy 90 astetta oikealle.

Väritetään neliön sisusta ja reunaviiva. Rivillä 2 määritellään reunan ja sisustan väri, rivillä 3 määritellään sisuksen värittämisen alku. Riveillä 4-6 tuotetaan neliö (laiskuuksissani käytän lyhenteitä komennoille) ja rivillä 7 lopetetaan sisustan väritys.

Neliöt ovat tylsiä, piirretään pentagrammi. Tästä näkee, että väritys toimii kuten GeoGebrassa. 

Jos haluaa muuttaa täytön sellaiseksi, että koko sisusta täyttyy, niin apuna voi käyttää ”nonzero” muuttujaa begin_fill-funktion muuttujana, kuten rivillä 19. Rivillä 3 muutetaan konnan nopeus suurimmaksi, eli syntyy vain valmis kuva, tämä toiminto pitää päättää rivin 27 done():lla. Riveillä 6-8 siirretään konna hieman vasemmalle perinteisin menetelmin, tässä versiossa saman asian ajaa rivin 18 jumpto-funktio.

Tähti

Jostain kumman syystä olen ihastunut tähtikuvioihin. Tehdään pieni matemaattinen pähkinä aiheeseen liittyen.

Miksi tahti(300, 5, 2) tuottaa tähden, kuten myös tahti(300, 9, 2), mutta tahti(300, 9, 6) ei tuota tähteä. Millaisilla m:n ja n:n arvoilla syntyy tähti? Saman tyyppinen appi löytyy GeoGebralla tuotettuna sivulla https://www.geogebra.org/m/rgVYFJrS

Alla oleva kuva on tahti(200, 10, 3)


Palaan aiheeseen lähiaikoina ja piirtelen fraktaaleja, nyt kun on käytössä vikkelä tapa tuottaa niitä suht’ koht simppelisti.

Lähteet

Larryn ohjesivu kirjastoon
https://larryriddle.agnesscott.org/ColabTurtlePlus/documentation2.html

”virallisen” Pythonin turtlekirjastosivu
https://docs.python.org/3/library/turtle.html

Turtle graphics Wikipediassa
https://en.wikipedia.org/wiki/Turtle_graphics

Seymort Papert Wikipediassa

https://en.wikipedia.org/wiki/Seymour_Papert

Lue

Seymort Papert : Lapset, tietokoneet, ajattelemisen taito, Kirjayhtymä, 1985

Ylioppilaskoekorrelaatiomatriisi koodi Pythonilla

Julkaisin muutama päivä sitten tarinan ”Kevään 22 yo-kirjoitusten tuloksien korrelaatiomatriisi Pythonilla”. Tässä artikkelissa kerron, millaisen koodin avulla tuotin sen. Käytän ohjelmointiympäristönä Googlen Colabia. Colabin etuna verrattuna muihin Python ympäristöihin (IDLE, Spyder yms.) on se, että voin muokata koodia pilven kautta ja Colabissa on lähes kaikki Big Datan käsittelyyn käytettävät kirjastot ovat helposti kätettävissä. Samalla saan helpon pääsyn omiin tiedostoihini Google Drivessä ja voin jakaa koodin helposti.

Esitän koodin kuvankaappauksina Colabista ja kommentoin niitä tarinan edetessä. Linkki lopulliseen tiedostoon löytyy tarinan  lopusta.

Tähän käytetty tiedosto löytyy ytl:n sivulta https://www.ylioppilastutkinto.fi/tietopalvelut/tilastot/koulukohtaisia-tunnuslukuja
sieltä löytyy linkki myös oppiainekoodeihin ja miten tiedostojen nimet on koodattu.

Itse tiedosto on osoitteessa https://www.ylioppilastutkinto.fi/ext/data/FT2022KD3001.csv

kirjastoista

Python on siitä kiva, että lähes mihin tahansa koodausongelmiin löytyy apua kirjastoista. Tässä tarinassa käytän Pandas, Seaborn ja Matplotlib -kirjastoja. 

Pandas on luotu taulukoidun datan käsittelyyn, se ikään kuin tuo taulukkolaskennan rivit ja sarakkeet koodiin. Taulukon tietotyyppi Pandasissa on Dataframe, yleensä kirjallisuudessa käytetylle taulukolle annetaan nimi df. Kun käyttää Pandasia, niin kannattaa ajatella taulukot siten, että rivit ovat tilastoyksikköjä ja sarakkeet muuttujia, kuten ytl:n datassa.

Matplotlib-kirjaston avulla piirretetään kuvaajia. Seaborn on Matplotlibin laajennus. Sen avulla saan taulukon dataan värikoodauksen heatmap-funktion avulla. 

koodi kommentoituna, pandas taulukko

Rivit 8-10: ladataan kirjastot

Rivi 13: on Ytl:n datan osoite

Rivi 15: luetaan data Pandasin taulukkoon. Tätä koodatessa havaitsin, että Ytl:n taulukossa erotin on puolipiste, niinkuin usein meillä skandinaaveilla. 

Tässä vaiheessa taulukko näyttää tältä. Jos rivin 16 olisi korvannut rivillä

display(talukko)

niin siitä olisi tullut nätimmmän näköisen, taas opin uutta. En jaksa muuttaa tarinaan liitettyjä kuvankaappauksia.

Kuvasta nähdään, että 24911 ylioppilasta valmistui tänä keväänä. Aakkosissa (tai jollain muulla logiikalla) ensimmäinen Vieremän lukion oppilas oli tyttö ja sai yhteensä 18 puoltoääntä jne.

Alla display-funktiolla tuotetun kuvan vasenta reunaa.

Rivillä 19 luodaan taulukosta df-niminen DataFrame-taulukko.

Rivillä 22 poistetaan kuusi vasemmanpuoleista saraketta ja oikeanpuolisin (tutkintotyyppi).

Taulukko df on nyt tämän näköinen.

Rivi 27: Lasketaan rivien summat (axis = 0 on rivit ja axis = 1 on sarakkeet). Funktio count laskee lukumäärät ja list tuottaa luvuista helposti käsiteltävän listan.

Rivit 30-33: Lasketaan sellaiset sarakkeet, joissa on alle 100 kirjoittajaa. 

Rivi 37: Poistetaan sellaiset sarakkeet, joissa on poistettava indeksi.

Edellisten rivien printtaus tuottaa tällaista.

Rivi 41: Lasketaan korrelaatiomatriisi, min_periods kertoo kuinka monta paria vähintään pitää olla ja round desimaalien lukumäärän. Oletuksena syntyy neliömatriisi, mikä on minulle parempi. LibreOffice ja Excel tuottavat työkaluillaan vain kolmiomatriiseja.

Tämä näyttää hyvältä.

Rivi 45 ja 47: Pitää poistaa vasemmasta reunasta tuo yht-sarake yhteenlaskuja varten.

Rivit 50-51: Lasketaan selitysasteiden summa ja niiden aineiden summa, joilla korrelaatio on yli 0.6. Tässä näkyy Pandasin käyttökelpoisuus taulukoidun datan käsittelyssä.

Nyt taulukon oikeassa reunassa on 

Jos tässä vaiheessa haluaisin tallentaa datan csv-tiedostona omaan Driveeni, niin se toimisi rivillä

df.to_csv(/content/drive/MyDrive/Artikkelit/matriisi/yo.csv", encoding="utf-8”)

seaborn

Tämän kirjaston avulla saan taulukkoon värikoodauksen käyttämällä heatmap-tyyppistä kuvaajaa. Erilaisia väripaletteja on aika paljon, valitsin tähän diskreetin (ei jatkuvan) paletin.  Tämän tuottaminen vaati aika paljon yritystä ja erehdystä.

Rivi 58: Valitaan diskreetti väripaletti keltaisesta punaiseen, päädyin kokeilujen jälkeen tuohon kuuteen eri väriin, ne kuvaavat MAOLin taulukoissa olevaa tulkintaa korrelaatiokertoimista. En välitä negatiivista korrelaatikertoimista, niitä kun on niin vähän.

Rivi 59: Tuotetaan heatmap, annot näyttää oikean reunan palkkin, vmax, vmin ja vcenter kertovat rajoista, annot_kws on fontin koko ja title otsikko.

Rivi 62: Tässä määritetään kuvan koko.

Viimein saatiin tämä kuva.

Oikean reunan kielien poistaminen toimii lisäämällä väliin rivit.

Nyt kuva on tällainen

koodaamisesta

Vaikka yllä oleva voi vaikuttaa aika suoraviivaiselta ja jopa ymmärrettävältäkin, niin tuon tuottaminen tällaiselta aloittelijalta vaati aika paljon Googlettamista sekä yritystä ja erehdystä. Koska Colabissa voi helposti kokeilla erilaisia versioita, niin pitää muistaa kirjoittaa paljon kommentteja. Muuten versioiden hallinta menee mahdottomaksi.

Colab-tiedosto https://colab.research.google.com/drive/106rjIDEJWdn2ImdVtjAKzg_3df9fWhPx?usp=sharing


Koodaamisen oppiminen on helppoa, sen opettaminen on vaikeaa.

lähteitä

Korrelaatiomatriisi Pandasilla https://datagy.io/python-correlation-matrix/

Pandas dataframe-ohje https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.corr.html

Seaborn väripaletit https://seaborn.pydata.org/tutorial/color_palettes.html

Seaborn Heatmap, aika hyvä ohje https://www.geeksforgeeks.org/seaborn-heatmap-a-comprehensive-guide/

Kalibur Rahman, Python Data Visualization, Essential Guide, 2021, BpB