Kirjoittaja: Antti Laaksonen (2006).
Tässä Ohjelmointiputkan uudessa opassarjassa käsitellään matematiikan aiheita, jotka ohjelmoijan on tärkeä tuntea. Monet oppaiden asiat opetetaan jossain vaiheessa peruskoulussa tai lukiossa, mutta sovelluksia käytännön ohjelmointiin ei ole aina helppo havaita. Oppaat on kirjoitettu enemmän kansantajuisesti kuin matemaattisen tarkasti: kuvia ja esimerkkejä on paljon, todistuksia taas niukasti. Ensimmäisen oppaan aiheena on monikäyttöinen jakojäännös.
Kokonaislukujen jakolaskun tuloksen voi ilmoittaa kahdella tavalla:
7 / 4 = 1,75
7 / 4 = 1 jää 3
Alemmalla rivillä oleva 3 on jakojäännös. Tämä on jakolaskussa yli jäävä osa. Kun jako menee tasan, jakojäännös on 0. Muussa tapauksessa jakojäännös on kokonaisluku, joka on jakajaa pienempi. Luvulla 4 jaettaessa jakojäännös voi siis olla 0, 1, 2 tai 3.
Esimerkki: Korissa oli 37 omenaa, jotka jaettiin viiden hengen kesken. Kuinka monta omenaa kukin sai ja kuinka monta omenaa jäi yli?
Vastaus: 37 / 5 = 7 jää 2. Jokainen sai seitsemän omenaa ja kaksi omenaa jäi yli.
Käytännössä omenat jaetaan niin, että kullekin syöjälle annetaan vuorollaan yksi omena, kunnes omenoita ei enää riitä koko kierrokseen. Jakolaskun tulos koostuu siis kahdesta osasta: kuinka monta kertaa jakaja mahtuu jaettavaan (osamäärä) ja kuinka paljon jää silloin yli (jakojäännös).
Esimerkki: Toisena päivänä jokainen sai viisi omenaa ja yksi jäi yli. Kuinka monta omenaa korissa oli, kun syöjiä oli taas viisi?
Vastaus: 5 * 5 + 1 = 26. Korissa oli 26 omenaa.
Jakojäännöksellä on suora yhteys luvun desimaaliosaan:
7 / 4 = 1 jää 3 = 1 + 3/4 = 1 + 0,75 = 1,75
Tuloksen desimaaliosa voidaan siis ilmoittaa murtolukuna, jossa osoittajana on jakojäännös ja nimittäjänä jakaja.
Tästä lähtien oppaassa käytetään seuraavia merkintöjä:
a / b = jakolaskun kokonaisosa
a mod b = jakolaskun jakojäännös
Siis esimerkiksi 7 / 3 = 2 ja 7 mod 3 = 1. Sana mod tulee siitä, että jakojäännöksen toinen nimi on modulo.
Ohjelmointikielissä jakojäännös merkitään tavallisimmin mod tai %.
Jos a mod 2 = 0, luku a on parillinen. Jos a mod b = 0, luku a on jaollinen luvulla b. Tällöin luku b on luvun a tekijä.
Esimerkki: Onko 6 luvun 220 tekijä?
Vastaus: 220 mod 6 = 4. Ei ole.
Esimerkki: Onko 7 luvun 175 tekijä?
Vastaus: 175 mod 7 = 0. 175 / 7 = 25. On, 7 * 25 = 175.
Kellotaulussa on 12 numeroa:
Kun viisari siirtyy numeron 12 kohdalle, kierros alkaa jälleen alusta. Viisarin aloituskohdan ja sen kulkeman matkan perusteella voidaan laskea viisarin uusi kohta jakojäännöksen avulla.
Esimerkki: Viisari on kello viiden kohdalla. Missä viisari on kymmenen tunnin kuluttua?
Vastaus: (5 + 10) mod 12 = 3. Kello kolmen kohdalla.
Sovelluksia:
Esimerkki: Kello on 16:00. Kuinka paljon kello on 52 tunnin kuluttua?
Vastaus: (16 + 52) mod 24 = 20. Kello on 20:00.
Esimerkki: Tänään on maanantai. Mikä viikonpäivä on 1000 päivän kuluttua?
Vastaus: 1000 mod 7 = 6. Siis sama viikonpäivä on 6 päivän kuluttua eli sunnuntai.
Esimerkki: Pekka jakoi kortteja neljään pinoon. Mihin pinoon meni 39. kortti?
Vastaus: 39 mod 4 = 3. Samaan pinoon kuin kolmas kortti eli kolmanteen pinoon.
Tällä tavalla voidaan ohjelmoinnissa tunnistaa joka toinen, joka kolmas jne. läpi käytävistä tiedoista. Laskurimuuttujan jakojäännös kertoo, missä kohtaa kierrosta mennään. Tietyllä jakojäännöksen arvolla voidaan tulostaa erivärinen teksti, rivinvaihto tai muuta vastaavaa.
Esimerkkejä:
C: Lukujen tulostus rivitettynä
PHP: Rivien väritys kolmella värillä
Tarkastellaan ruudukkoa, jossa on viisi pystyriviä ja viisi vaakariviä:
Jokainen ruutu on numeroitu vasemmalta oikealle ja ylhäältä alas. Lisäksi ruutuihin voi viitata ison ja pienen kirjaimen yhdistelmällä. Esimerkiksi ruudun Db numero on 16. Nyt tehtävänä on laskea ruudun numero kirjainparista ja päinvastoin. Kirjaimia voi laskuissa käsitellä numeroina niin, että A = 0, B = 1, C = 2, D = 3 ja E = 4 (pienet kirjaimet samoin).
Numero kirjaimista:
numero = rivi * 5 + sarake
Esimerkki: Mikä on ruudun Db numero?
Vastaus: Rivi = D = 3. Sarake = b = 1. Siis numero = 3 * 5 + 1 = 16.
Kirjaimet numerosta:
rivi = numero / 5
sarake = numero mod 5
Esimerkki: Mitkä ovat ruudun 16 kirjaimet?
Vastaus: Rivi = 16 / 5 = 3 = D. Sarake = 16 mod 5 = 1 = b. Siis Db.
Näitä kaavoja voi käyttää kaikenkokoisissa ruudukoissa. Luku 5 täytyy vain korvata ruudukon leveydellä.
Ohjelmoinnissa numero vastaa yksiulotteisen taulukon numerointia ja kirjainpari kaksiulotteisen taulukon numerointia.
Kuinka monta sekuntia on 2 päivää, 5 tuntia ja 10 minuuttia? Kuinka paljon on 191400 sekuntia?
Näihin kysymyksiin vastaamiseksi pitää tutkia, miten ajan yksiköt muodostuvat:
1 minuutti = 60 sekuntia
1 tunti = 60 minuuttia
1 päivä = 24 tuntia
1 viikko = 7 päivää
Näistä tiedoista on helppo laskea muitakin suhteita:
1 päivä = 24 * 60 * 60 = 86400 sekuntia
1 viikko = 7 * 24 = 168 tuntia
Ajan ilmoitus samassa yksikössä:
Lasketaan jokaisen yksikön suuruus halutussa yksikössä ja kerrotaan ajan osat.
Esimerkki: Kuinka monta sekuntia on 2 päivää, 5 tuntia ja 10 minuuttia?
Vastaus: 1 päivä = 86400 sekuntia. 1 tunti = 60 * 60 = 3600 sekuntia. 1 minuutti = 60 sekuntia. Siis: 2 * 86400 + 5 * 3600 + 10 * 60 = 191400 sekuntia.
Ajan ilmoitus eri yksiköissä:
Lasketaan jokaisen yksikön suuruus aloitusyksikössä. Jaetaan luku suurimmalla yksiköllä. Kokonaisosa on tämän yksikön määrä. Jakojäännös on uusi tarkasteltava luku. Tämä luku jaetaan toisiksi suurimmalla yksiköllä. Näin jatketaan, kunnes jakojäännös on 0.
Esimerkki: Kuinka paljon on 191400 sekuntia?
Vastaus: 1 päivä = 86400 sekuntia. 1 tunti = 3600 sekuntia. 1 minuutti = 60 sekuntia. 191400 / 86400 = 2 jää 18600. 18600 / 3600 = 5 jää 600. 600 / 60 = 10 jää 0. Siis 2 päivää, 5 tuntia ja 10 minuuttia.
Kuukausia ja vuosia ei voi laskea yhtä helposti ja yksiselitteisesti, koska niissä päivien määrä vaihtelee.
Esimerkki: Englannin vanha punta oli 20 shillinkiä, joka taas oli 12 pennyä. Kuinka paljon oli 1971 pennyä?
Vastaus: 1 punta = 20 * 12 = 240 pennyä. 1 shillinki = 12 pennyä. 1971 / 240 = 8 jää 51. 51 / 12 = 4 jää 3. Siis 8 puntaa, 4 shillinkiä ja 3 pennyä.
Alkuluku on luku, joka on jaollinen vain luvulla 1 ja itsellään.
Ensimmäiset alkuluvut ovat:
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37
On sovittu, että luku 1 ei ole alkuluku. Jokainen tätä suurempi kokonaisluku on joko alkuluku tai useamman alkuluvun tulo.
Kun luvusta ilmoitetaan sen muodostavat alkuluvut, puhutaan luvun alkutekijöistä. Luvun alkutekijät voi löytää jakamalla lukua pienempiin osiin.
250
= 10 * 25
= 2 * 5 * 5 * 5
Luvun alkutekijät ovat aina samat riippumatta luvun jakamisen vaiheista.
Nopeaa tapaa suurten lukujen alkutekijöiden etsimiseen ei tunneta.
Kahden luvun suurin yhteinen tekijä on suurin luku, jolla molemmat luvut ovat jaollisia. Esimerkiksi syt(40, 28) = 4.
Suurin yhteinen tekijä voidaan selvittää jakamalla luvut alkutekijöihin:
40 = 2 * 2 * 2 * 5
28 = 2 * 2 * 7
Yhteiset alkutekijät ovat 2 ja 2, joten syt(28, 20) = 2 * 2 = 4.
Näppärämpi tapa on käyttää Eukleideen algoritmia:
40 / 28 = 1 jää 12
28 / 12 = 2 jää 4
12 / 4 = 3 jää 0
Seuraavan laskun jaettava on edellisen jakaja, ja seuraavan laskun jakaja on edellisen jakojäännös. Kun jakojäännös on lopuksi 0, vastaus on sen laskun jakaja.
Esimerkki: Mikä on lukujen 1080 ja 1008 suurin yhteinen tekijä?
Vastaus: Käytetään Eukleideen algoritmia. 1080 / 1008 = 1 jää 72. 1008 / 72 = 14 jää 0. Siis syt(1080, 1008) = 72.
Kahden luvun pienin yhteinen moninkerta on pienin luku, joka on jaollinen kummallakin luvulla. Esimerkiksi pym(40, 28) = 280.
Myös pienin yhteinen moninkerta selviää lukujen alkutekijöistä:
40 = 2 * 2 * 2 * 5
28 = 2 * 2 * 7
Kustakin alkutekijästä valitaan suurin moninkerta, joka esiintyy jommassakummassa luvussa. Siis pym(40, 28) = 2 * 2 * 2 * 5 * 7 = 280.
Pienin yhteinen moninkerta voidaan laskea myös suoraan, jos tiedossa on suurin yhteinen tekijä:
pym(a, b) = (a * b) / syt(a, b)
Siis pym(40, 28) = (40 * 28) / syt(40, 28) = 1120 / 4 = 280
Esimerkki: Mikä on lukujen 1080 ja 1008 pienin yhteinen moninkerta?
Vastaus: Kun syt(1080, 1008) = 72, niin pym(1080, 1008) = (1080 * 1008) / 72 = 15120.
Esimerkkejä:
C: syt ja pym
QBasic: syt ja pym
Pienessä kylässä järjestetään tapahtumia seuraavasti:
Vuonna 2000 kaikki tapahtumat olivat samana vuonna. Koska näin tapahtuu seuraavan kerran?
Tämän tehtävän ratkaisu on kaikkien väliaikojen pienin yhteinen moninkerta:
pym(3, 4) = 12
pym(12, 6) = 12
Siis vuonna 2012 kaikki tapahtumat ovat jälleen samana vuonna.
Pienin yhteinen moninkerta lasketaan aina kahdelle luvulle, mutta kun lukuja on useampia, lasketaan ensin kahden ensimmäisen luvun pienin yhteinen moninkerta, sitten tämän tuloksen ja seuraavan luvun pienin yhteinen moninkerta jne.
Sama tehtävä eri sanoin: Hammasratas A:ssa on kolme hammasta, B:ssä neljä hammasta ja C:ssä kuusi hammasta. Jokainen hammasratas pyörii yhden askeleen sekunnissa. Milloin hammasrattaat ovat samassa tilanteessa kuin alussa?
Näin voidaan yleisemmin ratkaista tehtäviä, joissa on toisistaan riippumattomia eripituisia kiertoja, joiden täytyy päättyä yhtä aikaa. Esim. Putkaposti 8.
Voit lähettää palautetta ja kysymyksiä tästä oppaasta sähköpostilla osoitteeseen antti.laaksonen@ohjelmointiputka.net.
Kerro myös, mistä matematiikan alueesta haluaisit lukea tulevissa oppaissa!
Antti Laaksonen, 26.8.2006
Hieno opas! Opin paljon uutta mitä en jakojäännöksestä tiennytkään. Toivottavasti seuraava opas tulee piakkoin. :)
Varsin mielenkiintoinen. Varmasti pitää joskus lukea vielä uudestaan, kun en kaikkea vielä yhdellä kerralla sisäistänyt. Yhden virheen tosin huomasin tuolta oppaan alkuosasta: "Vastaus: 5 * 5 + 1 = 36. Korissa oli 36 omenaa". Oikea vastaushan olisi 26.
Koulussa on alettu käsitellä lukujonoja ja sarjoja. Olisi kiinnostavaa tietää, miten niitä on mahdollista hyödyntää ohjelmoinnissa (tällä hetkellä en tiedä niiden käyttötilanteista mitään, kun muutama tunti on vasta opiskeltu).
Hupsista vain, nyt virhe on korjattu.
"Lukujonot ja sarjat" oli mielestäni kiinnostava kurssi. Ohjelmoinnissa tulee usein vastaan lukujonoja, joille pitää keksiä kaava ("yleinen termi"). Esim. pisteitä pitää piirtää tasaisesti kohtiin 25, 30, 35, jne. Nyt huomataan, että kaava on 25 + 5n ja kohdat voi laskea suoraan silmukalla. Hyödyllisiä asioita kurssilla ovat mm. induktiotodistus, rekursio ja lukujonoihin liittyvät kaavat.
Todella hyvä opas. :)
Minua kiinnostaisi lukea tulevissa oppaissa Sin:istä ja Cos:istä ja niiden käytössä esimerkiksi peliohjelmoinnissa.
Tämähän on se opassarja mistä Antti silloin joskus keskustelussa kerroit, kun minä kyselin Sin:istä ja Cos:ista??
Joo, tämä on se opassarja. :) Seuraavaan oppaaseen tulee:
- Pythagoraan lause
- trigonometria (sin, cos ja kumppanit)
Loistavaa!
Tämä opassarja tulee todella tarpeeseen. :)
Ihan kiva opas, joskin minulle ei mitään uutta. Jossakin osassa olisi hyvä käsitellä mm. liukulukujen aiheuttamia pyöristysvirheitä laskuissa.
"Esimerkki: Pekka jakoi kortteja neljään pinoon. Mihin pinoon meni 39. kortti?
Vastaus: 39 mod 4 = 3. Neljänteen eli viimeiseen pinoon. "
Mahtaa kortti mennä 3.pinoon? Jos jakojäännös olisi 0 niin kortti menee viimeiseen pinoo. (kortit tasan)
Olet oikeassa, korjasin virheen.
Tarkka lukija voi pohtia, miksi 1 ei ole alkuluku. Sehän on jaollinen vain yhdellä ja itsellään.
Kyseessä on sopimus. Usein lukua 1 täytyy käsitellä eri tavalla kuin muita jaottomia lukuja, joten alkuluvun lyhyt nimitys on hyvä laittaa suoraan joukolle, joka alkaa {2,3,5,7,...}. Siihen pitää kuitenkin viitata niin usein, että "kaikki muut alkuluvut paitsi yksi" alkaisi pian jurppia. (Matematiikassa pyritään minimoimaan jurppiminen, mutta siinä ei yleisesti onnistuta.)
Tämän takia myös väite, että jokaisen positiivisen kokonaisluvun voi esittää alkulukujen tulona, ei päde tarkasti ottaen. Ykköstä ei voi esittää kuin ykkösten tulona.
Ehkä selvimmän esimerkin ykkösen erilaisesta käytöksestä saa, jos yrittää ohjelmoida Eratostheneen seulaa ja aloittaa kakkosen sijasta ykkösellä. Silloin jäävät löytyneet alkuluvut helposti vähiin.
Jos Antti siis haluat olla tarkka, voisit vaikka todeta yllä, että alkuluvut alkavat sopimuksen mukaan kahdesta ja tekijöihinjako alkulukuihin on mahdollista kaikilla kokonaisluvuilla n>=2.
Ohjelmoijan pitää kuitenkin olla tarkkana rajatapauksien kanssa. Siksi jaksan nipottaa :-)
Ja joku dynaamisella kielellä ohjelmoija voi haluta kokeilla, miten gcd ym. algoritmit käyttäyvät, jos niille ujuttaa vaivihkaa liukulukuargumentin tai pari. Merkkijonot yleensä poikkeavat pihalle tuon %-operaattoriin kohdalla, mutta se toimii mahdollisesti liukulukujen kanssa ihan hyvin.
Hyvä juttu. En haluaisi lisätä muuta kuin tuon kirjoittamani.
Oikein hyvä!
Minulle ollaan vuosien mittaan koulussa perusteltu ykkösen kuulumattomuutta alkulukuihin juuri tällä, että alkuluvun voi jakaa vain itsellään ja ykkösellä.
Nykyään tuotuntuu ainoalta järkevältä tavalta... Ylä asteella se joskus muinoin kummastutti.
Mitenkä muuten on? Luin joskus jostain (niimpä...) Että jos kaikki alkuluvut löydettäisiin niin salauksien purku helpottuisi älyttömästi.
Kopeekka:
Nyt asia on ilmaistu täsmällisemmin. Kohta muuttui vähän sekavammaksi, mutta olisi selvästi väärin väittää, että kaikki kokonaisluvut voisi esittää alkulukujen tulona. En ollut ajatellut asiaa aivan loppuun asti.
FrozenFire:
Joidenkin salausten toiminta perustuu siihen, että kahden suurenkin (alku)luvun tulon laskeminen on nopeaa, mutta tämän tulon jakaminen takaisin tekijöihin on hyvin hidasta. Siis salaisen tekstin saa selville, jos pystyy jakamaan annetun luvun tekijöihin, mutta kukaan ei tiedä nopeaa tapaa tähän.
Hyvin selkeästi esitetty kaikki asiat, niin että 9. luokkalainenkin sen tajuaa. =D Tästä on paljon hyötyä, kiitos siitä.
pym useimmiten tunnetaan pyj:na (pienin yhteinen jakaja). en ole koskaan nähnyt sitä kutsuttavan pymiksi.
wikipediassakin
http://fi.wikipedia.org/wiki/
tuntuu siltä olisit vääntänyt tuon monikerran englannista
least common multiple ...
Meille ainakin opetettiin logiikka ja lukuteoria -kurssilla juuri tuo pym (pienin yhteinen monikerta), ja ehkä joskus sivuhuomautuksena mainittiin synonyymiksi "pienin yhteinen jaettava".
Kiitos! Toivottavasti tässä oppaassa käsitellään kaikki tarpeellinen, ei varmasti tuolla datanomi-linjalla opeteta näitä :)
Hei!
Onnistuuko tehdä php:llä sellaista koodin pätkää, jolla voidaan laskea syt ihan millä tahansa luvuilla?
Ite yritin jotain saada aikaan, mutta ei toiminut :( :
$num1 = $_POST['num1']; //haetaan muuttujaan tiedot $num2 = $_POST['num2']; //haetaan muuttujaan tiedot for ($numer1 = $num1&&$numer2 = $num2; $jakojaannos >= 1; $numer1 = $numer2&&$numer2 = $jakojaannos) //alustetaan aluksi silmukka. Pyöritetään silmukkaa siihen asti että jakojäännös on 1. sitten päivitetään silmukka.. //..niin, että edellinen jakaja siirtyy jaettavaksi ja jakojäännös siirtyy jakajaksi. { $jakojaannos = $numer1%$numer2; //lasketaan $numer1 ja $numer2 jakojäännös if($jakojaannos == 0){ //jos $jakojaannos on 0.. echo $numer2 . "<br>"; //..tulostetaan $numer2 eli SYT }
Huomio! Kommentoi tässä ainoastaan tämän oppaan hyviä ja huonoja puolia. Älä kirjoita muita kysymyksiä tähän. Jos koodisi ei toimi tai tarvitset muuten vain apua ohjelmoinnissa, lähetä viesti keskusteluun.