Topic outline





  • Tehtävien perusvaatimukset

    Laskutehtävätyyppeihin calculated ja calculated simple tarvitaan aina

    • Kysymysteksti, jonka tulee sisältää yksi tai useampia muuttujia (ns. wildcardeja), jotka erotetaan tekstistä aaltosuluilla (ks. esimerkkejä alla)
    • Vastauskaava oikealle vastaukselle. Kaavassa on esiinnyttävä kaikki tehtävänannossa käytetyt muuttujat, joille halutaan muuttuvia arvoja.
    • Muuttujien (Wildcardien) määrittely, jonka mukaan järjestelmä arpoo satunnaislukuja wilcard-muuttujien arvoiksi, ja joista sitten annetulla vastauskaavalla systeemi laskee kutakin muuttujaa vastaavan oikean vastauksen. Oletusarvona wildcard-muuttujan arvoväli on (1,10). Tehtävän muuttujien arvovälin miettiminen on joskus hyvin oleellinen osa tehtävää, joko pelkästään sen kannalta, että tehtävä yleensä toimii oikein ja toisaalta myös sen takia, että vastausten arvoväli on kovin järkevä. Tavattoman suuria vastausarvoja kannattaa usein välttää, mikäli ne eivät ole täysin välttämättömiä.


    Perusesimerkkejä ilman matematiikkafunktioden käyttöä

    Alla muutamia esimerkkejä yksinkertaisista laskutehtävätyyppien kysymysteksteistä sekä kysymystä vastaavista vastauskaavasta, joissa käytetään ainoastaan peruslaskutoimituksia mutta ei vielä mitään varsinaisia matematiikkafunktioita. Nämä demonstroivat yksinkertaista muuttujien käyttöä tehtävänannoissa ja vastauskaavoissa. Matematiikkafunktioiden käyttöä esitellään myöhemmin.

    Esimerkki 1

    Kysymysteksti: Paljonko on {a}+{b}?

    Vastauskaava: {a}+{b}

    Esimerkki 2

    Kysymysteksti: Puhelinmyyjän kuukausiansiot ovat {perusansio} euroa (kiinteä summa) plus provisiona {provikka} prosenttia myytyjen tuotteiden arvosta. Odotusarvo myytyjen tuotteiden arvolle on {arvo_oa} tuhatta euroa. Mikä on myyjän kuukausiansion odotusarvo?

    Vastauskaava: {perusansio}+{provikka}/100*{arvo_oa}*1000 

    Huomaa: oletusarvoisilla muuttujan arvoväleillä (1,10) tehtävä ei ole käytännössä kovin realistinen sillä muuttujan {perusansio} arvoväli on oletusarvoilla epärealistisen pieni. Tämä voidaan ratkaista muuttamalla muuttujan arvoväliä tai määrittelemällä laskutoimitus kysymystekstiin (ks. alla).  

    Esimerkki 3  (laskutoimitus kysymystekstissä)

    Kysymysteksti: Puhelinmyyjän kuukausiansiot ovat {=100*{perusansio}} euroa (kiinteä summa) plus provisiona {provikka} prosenttia myytyjen tuotteiden arvosta. Myytyjen tuotteiden odotusarvo kuukaudessa on {arvo_oa} tuhatta euroa. Mikä on myyjän kuukausiansion odotusarvo?

    Vastauskaava: 100*{perusansio}+{provikka}/100*{arvo_oa}*1000 

    Huomaa: tässä kysymystekstissä käytettiin puhtaan muuttujan sijaan wildcard-laskutoimitusta {=100*{perusansio}}. Wildcard-laskutoimitukset kysymystekstissä laitetaan aaltosulkujen sisään ja aloittamalla laskutoimitus yhtäsuuruusmerkillä.  

    Esimerkki 4 (LaTex koodi ja wildcard kysymystekstissä)

    Kysymysteksti: Paljonko on \(log_6 6^{log_7 7^{{luku}}}\)?

    Vastauskaava: {luku}

    Huomaa: tässä tehtävässä käytettiin Latex-koodausta ja wildcard-muuttuja {luku} vietiin Latex-merkinnän sisään aaltosulkeissa. 

    Esimerkki 5 (Monta muuttujaa kysymyksessä, vastauksessa vain yksi)

    Kysymysteksti: Paljonko on \(log_{{kl1}} {{kl1}}^{log_{{kl2}} {{kl2}}^{{luku}}}\)?

    Vastauskaava: {luku}{kl1}*{kl2}/{kl1}/{kl2} eli efektiivisesti vain {luku}

    Huomaa: tämä tehtävä on muutoin samankaltainen kuin edellä, mutta tässä on nyt mukana lisäksi kaksi varioivaa logaritmin kantalukua {kl1} ja {kl2}, jotka eivät kuitenkaan vaikuta laskun lopputulokseen. Jotta kysymyksiin saadaan kuitenkin vaihtelua muuttujille {kl1} ja {kl2}, niin nämä on sisällytetty vastauskaavaan kertomalla ja jakamalla näillä muuttujilla.

    Esimerkki 6 (Monta muuttujaa kysymystekstissä, vastauksessa ei yhtään eli vakiovastaus)

    Kysymysteksti: Paljonko on \(log_{{kl1}} {{kl1}}^{log_{{kl2}} {{kl2}}^{7}}\)?

    Vastauskaava: 7*{kl1}*{kl2}/{kl1}/{kl2} eli efektiivisesti 7

    Huomaa: tämä tehtävä on muutoin samankaltainen kuin edellä, mutta nyt vastaus eri riipu mistään tehtävän muuttujista {kl1} ja {kl2}. Jotta kysymyksiin saadaan kuitenkin vaihtelua muuttujille {kl1} ja {kl2}, niin nämä on sisällytetty vastauskaavaan kertomalla ja jakamalla näillä muuttujilla.


    Matematiikkafunktioiden käyttö 

    Kysymyksissä voidaan käyttää pelkkien puhtaiden peruslaskutoimitusten lisäksi MyCoursesissa valmiina olevia perusmatematiikkafunktioita. Tämä funktiokirjasto on melko rajallinen, mutta sillä pystyy tekemään suurin piirtein kaiken sen, mitä hyvällä funktiolaskimella pystyy tekemään. Osaavissa käsissä näiden perusfunktioiden rajoituksia pystyy venyttämään. 


    Esimerkki 7

    Kysymysteksti: Oletetaan pankkitilille vuosikorko {korko} prosenttia vuodessa, ja korko liitetään pääomaan aina vuoden lopussa. Kuinka monen (kokonaisen) vuoden kuluttua pääoma on kasvanut 50 prosenttia alkuperäisestä?

    Vastauskaava: ceil(log(1.5)/log(1+{korko}/100))

    Huomaa: tässä tehtävässä käytettiin ceil-funktiota (pyöristys ylöspäin) ja log-funktiota (luonnollinen logaritmi). 

    Esimerkki 8 (vakiokuva mukana kysymyksen annossa) 

    Kysymysteksti: Oheisessa kuvassa on otosjakauma erään talousalueen laajakaistaliittymistä. Oletetaan, että alueen laajakaistatalouksissa keskimäärin joka kolmannessa on lisäksi laajakaistaan liittyvä viihdepaketti ja oletetaan lisäksi, että tämä on riippumatonta laajakaistan nopeudesta. Kuinka monessa nopean (yli 100Mb/s) liittymän taloudessa ei ole viihdepakettia, jos oletetaan koko talousalueen kooksi {n_ta}?   Vastaus pyöristettynä ylöspäin lähimpään kokonaislukuun. 

    Vastauskaava: ceil((210+78)/(76+360+210+78)*2/3*{n_ta}

    Esimerkki 9 (funktiorajoitteiden kiertämistä)

    Kysymysteksti: Anna on tekemässä perinteistä boolia isoäitinsä syntymäpäiväjuhliin.  Booliin käytetään 9UP nimistä limua, kahta erilaista likööriä \(X\) ja \(Y\) sekä Possu-viinaa, joiden alkoholipitoisuudet ovat 0, 18, 18 ja 37 prosenttia ja sokeripitoisuudet ovat 24, 18, 17 ja 3 prosenttia (kumpikin prosenttia tilavuusyksikköä kohti). Boolin perinteisiin kuuluu myös, että limua on 4 kertaa enemmän kuin likööriä \(Y\). Valmista boolia tulee saada 8.1 litraa, ja alkoholipitoisuuden tulee olla {pros} tilavuusprosenttia ja sokeripitoisuuden tulisi olla 21 tilavuusprosenttia. Kuinka monta litraa tarvitaan Possu-viinaa boolin valmistamiseen?

    Vastauskaava: 2.494245723-3.576982893*8.1*{pros}/100

    Huom: MyCoursesissa ei pysty ratkaisemaan matriisiyhtälöä \(Ax=b\), mutta tässä ratkaisu on toteutettu laskemalla käänteismatriisi erikseen ja dekomponoimalla ratkaisu yo. muotoon. Jotta tehtävä olisi järkevä, niin wildcard muuttujalle on erikseen selvitetty muuttujarajat (7.0, 8.5), jotka sitten on syötetty systeemiin.


    Muuttujien arvoväleistä Calculated tehtävätyypissä (ei siis koske  Calculated Simple tyyppiä)

    On hyvä tiedostaa MyCoursesin ominaisuus, että arvovälien määrittely ei laskutehtävätyypissä (calculated) toimi siten kuin sen odottaisi matemaattisesti toimivan määrittelyjoukkona. MyCourses toimii ilmeisesti tämän tehtävätyypin kohdalla siten, että järjestelmä testisijoittaa tehtävään ensiksi oman default arvovälin tasajakauma 1-10 arvoja, ja jos tämä ei tuota virheitä, niin vasta tämän jälkeen ottaa huomioon käyttäjän antaman arvovälin. Tässä kuitenkin törmätään ongelmaan, mikäli default-arvoväli sisältää vastauskaavan suhteen "kiellettyjä arvoja". Esimerkiksi vastauskaava sqrt({x}*(1-{x)}) tuottaa virheilmoituksen vaikka kuinka koittaisi määritellä x:n arvoväliksi (0-1), sillä järjestelmä syöttää alkuvaiheessa default-arvoväliltä (1,10) ykköstä suurempia arvoja, jotka tuottavat juurenottoa negatiitivista luvuista, josta seuraa virhetilanne. Jos tämän vastauskaavan sen sijaan kirjoittaa matemaattisesti ekvivalenttiin muotoon sqrt(x)*POW((1-{x})*(1-{x}),1/4) niin ongelmaa ei ole, sillä tämä kaava ei tuota negatiivista juurenottoa. Tiedostamalla etukäteen tämän calculated tehtävätyypin "ominaisuuden" on mahdolllista säästää melkoinen määrä työtä ja turhautumista. Tätä ongelmaa ei ole yksinkertaista laskutehtävää (calculated simple) käytettäessä.


    Vakiotehtävistä personoituja? 

    Tyypillisesti oppikirjojen ja muiden perinteisten materiaalien kysymykset ovat personoimattomia vakiotehtäväasetelmia, joissa kysymystekstit ja tehtävän vastaukset on kaikille yhteisiä. Suoraviivainen personointi laittamalla osa tai kaikki alkuperäisen tehtävän luvuarvot muuttujiksi ei aina ole teknisesti mahdollista johtuen lähinnä MyCoursesin rajatusta funktiokirjastosta. Myöskään sellaisen tehtävän personointi, jossa käytetään jotain tiettyä kiinteää ja oikeaa data-aineistoa ei onnistu suoraan, sillä data on ainutkertaista, 

    Ylimääräinen personoiva kerros tehtävässä 

    Personointi voidaan toteuttaa vakiotehtäväasetelman päälle ylimääräisenä kerroksena, jossa pohjalla on siis kaikille yhteinen vakiotehtävä ja päällä jokin personoiva kerros. 
    Esimerkki: kaikille yhteisestä datasetistä lasketaan joku kaikille yhteinen vakioarvo (lasketaan esim. keskiarvo), jota sitten edelleen käytetään personoivassa kerroksessa, jossa lasketaan joku opiskelijaspesifi muunnoslasku (lasketaan esimerkiksi skaalattu keskiarvo, jossa skaalauskerroin on jokaisella opiskelijalla erilainen).

    Personointi kuvaajissa

    Kuvaajissa personointia voi toteuttaa esimerkiksi käyttämällä kuvaajia, jossa asteikot eivät ole numeraalisia vaan parametrisoitu jollain opiskelijaspesifillä parametrillä. 

    Esimerkki 10 (personointi kuvaajassa)

    Kysymysteksti: Oletetaan, että vaihtuvakorkoisen säästötilin vuosikorot kolmen vuoden ajalta noudattavat oheista kuvaajaa, jossa parametri a={oma_korko}. Mikä on {=1000*{alku}} euron alkupääoman suuruus kahden vuoden kuluttua sijoituksesta, kun vuoden aikana kerätty korko lisätään aina pääomaan vuoden lopussa? 

    Vastauskaava: 1000*{alku}*(1+{oma_korko}/100)*(1+2*{oma_korko}/100) 


    Ehdollinen laskukaava eli (jonkinlainen) IF-lause

    MyCoursesissa ei toistaiseksi ole tarjolla mitään yksinkertaista tapaa tehdä ehdollista laskutoimitusta esimerkiksi toteuttamaan seuraavaa ongelmaa, jossa hinta riippuu tilausmäärästä

    • jos {tilausmaara} > raja_arvo niin vastaus on {tilausmaara}*1.51
    • jos {tilausmaara} < raja_arvo niin vastaus on {tilausmaara}*1.70

    Varsinaisissa ohjelmointikielissä tämän voisi helposti toteuttaa IF-lauseella, jota sellaisenaan ei kuitenkaan ole käytössä MyCoursesissa. Tätä puutetta on kuitenkin mahdollista kiertää kikalla, joka hyväksikäyttää tarjolla olevaa is_finite funktiota, jolla voidaan rakentaa ylläoleva ehdollinen vastauskaava seuraavasti (raja_arvo=100)

    Vastauskaavabindec(is_finite(log({tilausmaara}-100)))*{tilausmaara}*1.51+bindec(is_finite(log(100-{tilausmaara})))*{tilausmaara}*1.70

    Tässä kaavassa is_finite(log({tilausmaara}-100))  tsekkaa, että muuttuja 'tilausmaara' on suurempi kuin 100 (logaritmi negatiivisesta luvusta ei tuota validia lukuarvoa) ja vastaavasti is_finite(log(100-{tilausmaara}))  tsekkaa, että muuttuja 'tilausmaara' on pienempi kuin 100. Funktio is_finite tuottaa outputtina binaariarvon, joka pitää muuttaa laskutoimitusta varten tavalliseksi desimaaliluvuksi funktiolla bindec. Kun nämä kaksi toisensa poissulkevaa tapahtumaa summataan yhteen saadaan toteutettua ylläoleva ehdollinen laskukaava.

    Samalla idealla voi toteuttaa muitakin ehdollisia laskukaavoja, joskin yhtään eksoottisempien ehdollisten laskukaavojen kirjoittaminen tällä kikalla tulee helposti haastavaksi, eikä kaikkea edes pysty toteuttamaan (mielekkäästi) tarjolla olevilla is_finite, is_infinite, is_nan -funktioilla. Jos/kun tällaisia IF-rakenteita ehdottomasti haluaa toteuttaa, niin Stack on todennäköisesti huomattavasti parempi vaihtoehto. 


    Tilastolliset laskut

    MyCoursesissa ei ole muutamien matematiikkafunktioiden lisäksi käytössä mitään valmiita tilastofunktioita ja siten esim. tilastollisten tunnuslukujen lasku yhtään isommista satunnaisotoksista (n kappaletta erillisiä wildcardeja) voi käytännössä olla vaikeaa, jota seuraava esimerkki valaisee

    • Kysymysteksti:
      Laske harhaton otosvarianssi seuraavista luvuista: {l1},{l2},{l3},{l4},{l5},{l6},{l7},{l8},{l9},{l10}.
    • Vastauskaava:
      (pow( ({l1}-(({l1}+{l2}+{l3}+{l4}+{l5}+{l6}+{l7}+{l8}+{l9}+{l10})/10)),2)+pow( ({l2}-(({l1}+{l2}+{l3}+{l4}+{l5}+{l6}+{l7}+{l8}+{l9}+{l10})/10)),2)+pow( ({l3}-(({l1}+{l2}+{l3}+{l4}+{l5}+{l6}+{l7}+{l8}+{l9}+{l10})/10)),2)+pow( ({l4}-(({l1}+{l2}+{l3}+{l4}+{l5}+{l6}+{l7}+{l8}+{l9}+{l10})/10)),2)+pow( ({l5}-(({l1}+{l2}+{l3}+{l4}+{l5}+{l6}+{l7}+{l8}+{l9}+{l10})/10)),2)+pow( ({l6}-(({l1}+{l2}+{l3}+{l4}+{l5}+{l6}+{l7}+{l8}+{l9}+{l10})/10)),2)+pow( ({l7}-(({l1}+{l2}+{l3}+{l4}+{l5}+{l6}+{l7}+{l8}+{l9}+{l10})/10)),2)+pow( ({l8}-(({l1}+{l2}+{l3}+{l4}+{l5}+{l6}+{l7}+{l8}+{l9}+{l10})/10)),2)+pow( ({l9}-(({l1}+{l2}+{l3}+{l4}+{l5}+{l6}+{l7}+{l8}+{l9}+{l10})/10)),2)+pow( ({l10}-(({l1}+{l2}+{l3}+{l4}+{l5}+{l6}+{l7}+{l8}+{l9}+{l10})/10)),2))/9 

    Eli yksinkertaisen otosvarianssin kymmenestä generoidusta luvusta onnistuu kyllä periaatteessa, mutta käytännössä tuollaisen vastauskaavan kirjoittaminen ja debuggaaminen on hyvin työlästä ja virhealtista - MyCourses ei myöskään salli mitään lukemista ja editointia helpottavia rivivaihtoja vastauskaavassa ja yhtään pidempien vastauskaavojen hahmotteluun joku ulkoinen editori sulkukorostuksilla on melkein välttämättömyys.

    Tilastofunktioita on vuosien saatossa toivottu sisällytettäväksi valmisfunktiokirjastoon, mutta koska laskutehtävätyyppien kehitys on ilmeisesti yhden vapaaehtoisen henkilön takana, niin aikataulusta ei ole mitään tietoja. MyCoursesiin/Moodleen on tosin saatavissa joitain yksittäisiä tilastofunktiota sisältäviä lisäpaketteja, mutta näiden saaminen käyttöön ei välttämättä ole kovin yksinkertaista. Toki joitakin yksinkertaisia tilastollisia ja todennäköisyyslaskentaan liittyviä suureita voi laskea helposti tai kohtuullisen helposti ihan peruslaskutoimituksia ja perusfunktioita käyttäen. Tämä voi kuitenkin vaatia opettajalta hieman luovaa ajattelua ja ongelmanratkaisua sekä mahdollisesti ylimääräistä työpanosta.


    Numeriikasta ja numeeristen ongelmien välttämisestä

    MyCoursesin laskumoottori perustuu ilmeisesti perustason PHP-laskumoottoriin eikä siten toteuta numeriikan suhteen kaikkein kovimpia vaatimuksia. Yleisesti ottaen numeriikan kanssa voi tulla ongelmia jos laskee yhteen/kertoo/jakaa tosi isoja ja pieniä lukuja keskenään. Ratkaisuna tähän on tehtävänannon tai laskukaavan muuttaminen jollakin tavalla sellaiseksi, että käytetyt lukuarvot ovat suuruusluokaltaan lähempänä toisiaan.