Arvon palauttavat funktiot

Tarkastellaan vähän toisenlaista versiota sijoituksen arvon kehittymisen laskevasta ohjelmasta: tällä kerralla käyttäjä haluaa vertailla useaa eri sijoitusmahdollisuutta, joilla on eri vuosituotto. Käyttäjällä on mielessään sijoitettava pääoma ja sijoitusaika ja hän haluaa vertailla pääoman arvoa sijoitusajan jälkeen eri sijoitustavoissa.

Ohjelmassa käyttäjä antaa oletetun vuosituoton käyttötilille, sijoitustilille, korkorahastosijoitukselle ja osakerahastosijoitukselle. Ohjelma laskee käyttäjän antaman pääoman arvon annetun sijoitusajan jälkeen ja tulostaa pääoman ennustetun arvon eri sijoitustavoille.

Tässä ohjelmassa pääoman arvo sijoitusajan jälkeen pitää laskea neljä eri kertaa. Jokaisella kerralla käytetään samaa kaavaa, mutta käytetty vuosituottoprosentti vaihtelee. On siis järkevää tehdä oma funktio, joka saa parametrina pääoman, sijoitusajan ja tuottoprosentin ja laskee pääoman arvon sijoitusajan jälkeen.

Tällä kerralla ei kuitenkaan haluta, että arvon laskeva funktio tulostaa käyttäjälle sijoituksen arvon, vaan tulostus halutaan tehdä pääohjelmassa. Näin funktiota voidaan käyttää monipuolisemmin, kun sen laskeman arvon tulostus on erotettu itse laskemisesta. Funktion laskema arvo voidaan tulostaa ohjelmassa vasta selvästi myöhemmin kuin itse laskeminen tapahtui tai laskettua arvoa voidaan käyttää ohjelmassa myöhemmin hyväksi.

Määritellään siis funktio laske_arvo, joka laskee sijoituksen arvon annetun sijoitusajan jälkeen. Alkuperäinen pääoma, sijoitusaika ja vuosittainen tuottoprosentti annetaan tälle funktiolle parametreina. Nyt tarvitaan kuitenkin jokin keino, jolla pääohjelma saa tietoonsa funktion laskeman arvon, jotta tätä arvoa voitaisiin käyttää pääohjelmassa. Tähän tarkoitukseen käytetään arvon palauttamista.

Funktio saadaan palauttamaan jokin arvo kirjoittamalla

return lauseke

missä lauseke voi olla mikä tahansa lauseke, jonka arvo voidaan laskea, myös pelkkä muuttujan nimi. Arvon palauttaminen tarkoittaa sitä, että lasketaan lausekkeen arvo, päätetään funktion suoritus ja palataan takaisin sinne kohtaan, missä funktiota kutsuttiin. Tässä kohdassa funktion palauttama lausekkeen arvo on käytettävissä: se voidaan esimerkiksi ottaa talteen johonkin muuttujaan sijoituskäskyn avulla tai tulostaa suoraan print-käskyssä. Tätä selvennetään alla olevassa esimerkissä.

Funktio laske_arvo voidaan kirjoittaa esimerkiksi seuraavasti:

def laske_arvo(paaoma, aika, vuosituotto):
    loppuarvo = (1.0 + vuosituotto/100.0) ** aika * paaoma
    return loppuarvo
Lasketaan sijoituksen arvo annettujen vuosien jälkeen.
Sijoitetaan laskettu arvo muuttujan loppuarvo arvoksi.
Palautetaan muuttujan loppuarvo arvo.

Palautettu arvo saadaan käyttöön siellä, missä funktiota kutsutaan esimerkiksi sijoittamalla arvo johonkin muuttujaan seuraavasti:

sijoituksen_arvo = laske_arvo(10000, 5, 4.0)

Tässä on kutsuttu funktiota laske_arvo suluissa annetuilla parametrien arvoilla. Funktion suorittamisen jälkeen sen palauttama arvo on sijoitettu muuttujaan sijoituksen_arvo. Tämän jälkeen muuttujaa sijoituksen_arvo voi käyttää ohjelmassa samaan tapaan kuin mitä tahansa muuta muuttujaa. Sijoituskäsky siis suoritetaan ihan samalla tavalla kuin aikaisemmissa esimerkeissä esitetyt sijoituskäskyt: Ensin lasketaan sijoituskäskyn oikealla puolella olevan lausekkeen arvo, mikä funktiokutsun tapauksessa tarkoittaa kutsutun funktion suorittamista suluissa annetuilla parametrien arvoilla. Tämän jälkeen lausekkeen arvo eli funktion palauttama arvo annetaan arvoksi sijoituskäskyn vasemmalla puolella olevalle muuttujalle. Voit tutkia funktion ja sen kutsun toimintaa vielä alla olevan animaation avulla:

Funktion palauttamaa arvoa voidaan käyttää myös suoraan ilman että arvo tallennetaan minkään muuttujan arvoksi, esimerkiksi seuraavasti

print("Arvo lopuksi", laske_arvo(10000, 5, 4.0))

Tässä kutsutaan ensin funktiota laske_arvo, suoritetaan funktio ja sen jälkeen tulostetaan funktion palauttama arvo yhdessä muun print-käskyssä annetun tekstin kanssa. Tässä tapauksessa funktion palauttamaa arvoa ei ole kuitenkaan tallennettu minkään muuttujan arvoksi, joten arvoa ei voida käyttää ohjelmassa enää tämän jälkeen muuten kuin kutsumalla funktiota uudestaan.

Myös funktio laske_arvo voidaan kirjoittaa toisella tavalla kuin edellä on esitetty. Kuten kerrottiin, return-käskyssä voi palautettavana arvona olla mikä tahansa lauseke, jonka arvo voidaan laskea. Niinpä ei ole mikään pakko tallentaa funktion laskemaa arvoa johonkin muuttujaan ennen return-käskyn suorittamista, vaan laskettava lauseke voidaan kirjoittaa suoraan return-käskyyn seuraavan esimerkin mukaisesti:

def laske_arvo2(paaoma, aika, vuosituotto):
    return (1.0 + vuosituotto/100.0) ** aika * paaoma

Tässä lasketaan ensin return-käskyssä olevan lausekkeen arvo ja palautetaan se samalla kun lopetetaan funktion suoritus. Funktiota voidaan kutsua ja sen palauttamaa arvoa käyttää ihan samalla tavalla kuin edellisessä esimerkissä.

Seuraavaksi esimerkkiohjelma, joka pyytää käyttäjältä sijoitettavan pääoman, sijoitusajan vuosina sekä oletetut tuottoprosentit eri sijoitusmuodoille. Ohjelma tulostaa sijoitusten arvon sijoitusajan jälkeen.

def laske_arvo(paaoma, aika, vuosituotto):
    loppuarvo = (1.0 + vuosituotto/100.0) ** aika * paaoma
    return loppuarvo


def main():
    rivi = input("Anna sijoitettava paaoma: ")
    rahamaara = float(rivi)
    rivi = input("Anna sijoitusaika vuosina: ")
    vuodet = int(rivi)
    rivi = input("Anna kayttotilin korko: ")
    korko = float(rivi)
    kayttotilisijoitus = laske_arvo(rahamaara, vuodet, korko)
    rivi = input("Anna sijoitustilin korko: ")
    korko = float(rivi)
    sijoitustilisijoitus = laske_arvo(rahamaara, vuodet, korko)
    rivi = input("Anna korkorahaston vuosituotto: ")
    korko = float(rivi)
    korkorahastosijoitus = laske_arvo(rahamaara, vuodet, korko)
    rivi = input("Anna osakerahaston vuosituotto: ")
    korko = float(rivi)
    osakerahastosijoitus = laske_arvo(rahamaara, vuodet, korko)
    print("Sijoitusten arvo", vuodet, "vuoden paasta:")
    print("Kayttotili:", kayttotilisijoitus, "euroa")
    print("Sijoitustili:", sijoitustilisijoitus, "euroa")
    print("Korkorahasto:", korkorahastosijoitus, "euroa")
    print("Osakerahasto", osakerahastosijoitus, "euroa")


main()

Python-ohjelmissa yksi funktio voi myös palauttaa kerralla useamman arvon, jotka voidaan ottaa talteen samanaikaisella sijoituksella. Tarkastellaan esimerkkinä seuraavaa ongelmaa: Internetissä ja urheilulehdissä on hyvin paljon erilaisia harjoitusohjelmia juoksuharrastuksen aloittamiseen ja kehittämiseen. Ongelma on kuitenkin se, että englanninkielisillä sivuilla ja lehdissä on yleensä annettu ohjeelliset juoksunopeudet juostavaa mailia kohti, kun taas suomalainen haluaisi tarkastella nopeutta kilometriä kohti. Kirjoitetaan ohjelma, jonka avulla käyttäjä voi helposti muuttaa esimerkiksi harjoitusohjelmassa annetun nopeusohjeen 8 min 5 s – 9 min 30 s / maili nopeudeksi kilometriä kohti.

Nopeusmuunnosta varten kirjoitetaan funktio muuta_km_vauhdiksi, joka saa parametrina mailinopeuden minuutit ja sekunnit ja muuttaa mailinopeuden nopeudeksi kilometriä kohti. Funktion halutaan palauttavan arvonaan sekä kilometrivauhdin minuutit että sekunnit. Tämä voidaan tehdä kirjoittamalla return-käskyyn molemmat palautettavat arvot pilkulla erotettuna.

return km_minuutit, km_sekunnit

Funktion palauttamat arvot voidaan ottaa talteen esimerkiksi muuttujiin ala_min ja ala_s seuraavalla sijoituskäskyllä:

ala_min, ala_s = muuta_km_vauhdiksi(maili_minuutit, maili_sekunnit)

Alla on funktion muuta_km_vauhdiksi koodi:

def muuta_km_vauhdiksi(minuutit, sekunnit):
    MAILIKERROIN = 1.609344
    km_vauhti = int ((minuutit * 60 + sekunnit) / MAILIKERROIN)
    km_minuutit = km_vauhti // 60
    km_sekunnit = km_vauhti % 60
    return km_minuutit, km_sekunnit
Lasketaan yhteen mailiin kuluvat sekunnit.
Lasketaan, montako sekuntia kuluu kilometriä kohti.
Lasketaan katkaisevan jakolaskun avulla, montako kokonaista minuuttia kuluu kilometriä kohti.
Lasketaan jakojäännöksen avulla, montako sekuntia kokonaisten minuuttien jälkeen jää yli kilometriä kohti.
Palautetaan kaksi eri arvoa sinne, missä funktiota kutsuttiin.

Alla on esimerkki pääohjelmasta, joka pyytää käyttäjältä kaksi eri mailinopeutta ja muuntaa ne annetun funktion avulla kilometrinopeuksiksi.

def main():
    rivi = input("Anna nopeuden alarajan minuutit: ")
    maili_min = int(rivi)
    rivi = input("Anna nopeuden alarajan sekunnit: ")
    maili_sek = int(rivi)
    ala_min, ala_s = muuta_km_vauhdiksi(maili_min, maili_sek)
    rivi = input("Anna nopeuden ylarajan minuutit: ")
    maili_min = int(rivi)
    rivi = input("Anna nopeuden ylarajan sekunnit: ")
    maili_sek = int(rivi)
    yla_min, yla_s = muuta_km_vauhdiksi(maili_min, maili_sek)
    print("Suositeltu nopeus on", ala_min, "min", ala_s, "s / km -",
          yla_min, "min", yla_s, "s / km")


main()
Kutsutaan funktiota muuta_km_vauhdiksi. Tallennetaan sen ensimmäinen paluuarvo muuttujaan ala_min ja toinen paluuarvo muuttujaan ala_s.
Kutsutaan funktiota muuta_km_vauhdiksi. Tallennetaan sen ensimmäinen paluuarvo muuttujaan yla_min ja toinen paluuarvo muuttujaan yla_s.

Esimerkki ohjelman suorituksesta:

Anna nopeuden alarajan minuutit: 8
Anna nopeuden alarajan sekunnit: 5
Anna nopeuden ylarajan minuutit: 9
Anna nopeuden ylarajan sekunnit: 30
Suositeltu nopeus on 5 min 1 s / km - 5 min 54 s / km

Sisäkkäiset funktiokutsut

Kuten aikaisemmin on todettu, funktiota kutsuttaessa parametrina voidaan antaa mikä tahansa lauseke, jonka arvo voidaan laskea. Myös toisen funktion kutsu on tällainen lauseke. Voidaan siis kirjoittaa funktion kutsu, jonka sisällä on parametrin arvona toisen (tai joissakin tapauksissa myös saman) funktion kutsu. Tällöin aina sisempi funktiokutsu suoritetaan ensin, ja sen paluuarvoa käytetään ulomman funktion parametrina.

Hyvin tyypillinen esimerkki sisäkkäisistä funktiokutsuista on tilanne, jossa käyttäjältä luetaan arvo Pythonin valmiin input-funktion avulla ja tämä arvo pitää sitten muuttaa kokonais- tai desimaaliluvuksi Pythonin valmiin int- tai float-funktion avulla. Tähän asti olleissa esimerkeissä tämä on tehty kahdella eri ohjelmarivillä, joista ensimmäisellä luetaan haluttu arvo ja toisella se muutetaan sopivan tyyppiseksi luvuksi, esimerkiksi:

rivi = input("Anna nopeuden ylarajan sekunnit: ")
maili_sek = int(rivi)

Käskyt voidaan kuitenkin yhdistää yhdelle riville, jos input-funktion kutsu annetaan suoraan int-funktion parametrina:

maili_sek = int(input("Anna nopeuden ylarajan sekunnit: "))

Nyt siis suoritetaan ensin sulkujen sisällä oleva input-funktion kutsu, joka pyytää ja lukee käyttäjältä sekuntien arvon. Funktio palauttaa käyttäjältä saadun arvon merkkijonona. Tämä merkkijono tulee ulomman int-funktion kutsun parametrin arvoksi. Funktio int taas palauttaa sille parametrina annettua merkkijonoa vastaavan kokonaisluvun. Rivin suoritus on vielä esitetty seuraavassa animaatiossa:

Pythonin valmiit kirjastot ja moduuli math

Pythoniin on määritelty valmiiksi suuri joukko funktioita erilaisten toimintojen tekemiseen. Suuri osa näistä funktioista on ryhmitelty kirjastoihin. Tyypillisesti yhteen kirjastoon on koottu joukko samaan aiheeseen liittyviä valmiita funktioita ja mahdollisesti myös vakioita. Näitä kirjastoja nimetetään Pythonissa moduuleiksi. Python-tulkin mukana tulee esimerkiksi moduuli math, joka sisältää erilaisia matemaattisia funktioita (esimerkiksi neliöjuuren laskemiseeen) ja vakioita, sekä kirjasto random, jossa on taas satunnaislukujen generoimiseen tarkoitettuja funktioita, joiden avulla voi jäljitellä lukujen arpomista.

Python-tulkin mukana tulevien kirjastojen lisäksi on julkisesti vapaasti saatavilla suuri joukko muita Python-kirjastoja, esimerkiksi NumPy tieteellistä laskentaa (esimerkiksi isojen matriisien tehokasta käsittelyä) varten ja Pandas datan käsittelyyn ja analysointiin.

Seuraavaksi käsitellään moduulia math ja sen sisältämiä funktioita ja vakioita. Kirjasto on asennettu valmiiksi Python-tulkin mukana, mutta jotta sen funktioita voisi käyttää, pitää ohjelmatiedoston alussa ensin kertoa, että ohjelmassa käytetään tätä kirjastoa. Se tehdään kirjoittamalla

import math

Tämän jälkeen ohjelmassa voidaan kutsua kirjaston sisältämiä funktioita kirjoittamalla ensin math. ja sen jälkeen funktion nimi, esimerkiksi luvun 17 neliöjuuri voidaan laskea kirjoittamalla

math.sqrt(17)

Alla olevaan taulukkoon on koottu joitakin tärkeimpiä math-moduulin sisältämiä funktioita. Taulukko ei sisällä läheskään kaikkia funktioita. Kattavan listan voi lukea Pythonin omasta dokumentaatiosta (linkki).

Funktio Selitys
ceil(x) pienin kokonaisluku, joka on \(\ge x\)
floor(x) suurin kokonaisluku, joka on \(\le x\)
trunc(x) x:n kokonaisosa ilman pyöristyksiä
sqrt(x) neliöjuuri
exp(x) e potenssiin x
log(x) luonnollinen logaritmi
log2(x) 2-kantainen logaritmi
log10(x) 10-kantainen logaritmi
cos(x) kosini
sin(x) sini
tan(x) tangentti

Funktioiden lisäksi moduulissa on määritelty myös joitakin matemaattisia vakioita, esimerkiksi alla olevassa taulukossa esitetyt

Vakio Selitys
math.pi pii
math.e luonnollisen logaritmin kantaluku
math.inf suurin mahdollinen float-tyyppinen arvo

Esimerkki

Oletetaan, että kesämökille on kaksi mahdollista reittiä: sinne voi kulkea kuvan mukaista tietä pitkin. Tie muodostaa suorakulmaisen kolmion kaksi sivua (kateetit). Toinen vaihtoehto on oikaista suoraan pellon ja metsän kautta. Suorempi reitti on selvästi lyhyempi (em. suorakulmaisen kolmion hypotenuusa), mutta hidaskulkuisempi.

../_images/matkareitti.gif

Kirjoitetaan ohjelma, joka kysyy käyttäjältä tietä pitkin kulkevan reitin osien pituudet sekä käyttäjän nopeuden tiellä ja oikoreitillä. Ohjelma laskee ja tulostaa reitin pituuden kumpaakin kautta sekä kumpaakin vaihtoehtoon kuluneen ajan.

Oikoreitin pituuden laskemisessa käytetään pythagoraan lausetta: suorakulmaisen kolmion hypotenuusan pituuden voi laskea ottamalla neliöjuuren sen kateettien neliöiden summasta. Eli korotetaan kummankin kateetin pituus toiseen potenssiin, lasketaan näiden summa ja otetaan neliöjuuri tästä summasta. Näin on tehty alla olevassa esimerkkiohjelmassa.

import math

def main():
    nopeus_tiella = float(input("Anna nopeus tieta pitkin (km/h)\n"))
    nopeus_oikoreitilla = float(input("Anna nopeus oikoreittia pitkin (km/h)\n"))
    sivu1 = float(input("Anna ensimmaisen tieosuuden pituus (km)\n"))
    sivu2 = float(input("Anna toisen tieosuuden pituus (km)\n"))
    oikoreitti = math.sqrt(sivu1 ** 2 + sivu2 ** 2)
    aika_tie = (sivu1 + sivu2) / nopeus_tiella
    aika_oikoreitti = oikoreitti / nopeus_oikoreitilla
    print(f"Matka tieta pitkin on {sivu1 + sivu2:.2f} km,")
    print(f"ja siihen menee aikaa {aika_tie:.1f} h.")
    print(f"Matka oikoreittia pitkin on {oikoreitti:.2f} km,")
    print(f"ja siihen menee aikaa {aika_oikoreitti:.1f} h.")

main()

Alla on esimerkki ohjelman suorituksesta.

Anna nopeus tieta pitkin (km/h)
7.0
Anna nopeus oikoreittia pitkin (km/h)
2.5
Anna ensimmaisen tieosuuden pituus (km)
7.0
Anna toisen tieosuuden pituus (km)
4.0
Matka tieta pitkin on 11.00 km,
ja siihen menee aikaa 1.6 h.
Matka oikoreittia pitkin on 8.06 km,
ja siihen menee aikaa 3.2 h.

Totuusarvon palauttavat funktiot ja niiden paluuarvon käyttö

Aikaisemmissa esimerkeissä funktion paluuarvo oli yksittäinen tai useampi luku. Monesti ohjelmia kirjoitettaessa on kuitenkin kätevää kirjoittaa erilaisiin tarkistuksiin funktioita, jotka tarkistavat, onko jokin ehto tosi vai epätosi ja palauttavat sen mukaan joko arvon True tai False. Tällaista paluuarvoa voidaan sitten käyttää esimerkiksi if- tai while-käskyn ehdossa.

Tarkastellaan seuraavaa esimerkkiä: halutaan kirjoittaa ohjelma, joka laskee kahden tason suoran leikkauspisteen. Suoraa kuvaava yhtälö annetaan muodossa \(ax + by + c = 0\), missä \(a\), \(b\) ja \(c\) ovat kokonaislukuja. Leikkauspiste voidaan laskea muodostamalla suoria kuvaavista yhtälöistä yhtälöpari ja ratkaisemalla tämä yhtälöpari.

Leikkauspisteen laskemisessa tulee kuitenkin vastaan erilaisia erikoistapauksia:

  • Suorat voivat olla yhtenevät eli niillä on sama kulmakerroin ja sama leikkauspiste y-akselin kanssa. Tällöin suorat leikkaavat toisensa koko ajan eikä niillä ole yhtä leikkauspistettä.
  • Suorat voivat olla yhdensuuntaiset, mutta erilliset. Niillä on siis sama kulmakerroin, mutta ne leikkaavat y-akselin eri pisteissä. Tällöin suorilla ei ole lainkaan leikkauspisteitä.
  • Molemmat suorat ovat y-akselin suuntaisia. Tällöin ne ovat joko yhtenevät tai sitten yhdensuuntaiset mutta erilliset sen mukaan, leikkaavatko ne x-akselin samassa vai eri kohdassa.

Näissä tapauksissa ei voida käyttää suoraan yhtälöryhmän ratkaisevaa kaavaa, vaan tapaukset on käsiteltävä erikseen.

Erikoistapausten käsittelemistä varten kannattaa kirjoittaa oma funktio, joka tarkistaa, onko kahdella suoralla sama kulmakerroin, ja toinen funktio, joka tarkistaa, onko kahden yhdensuuntaisen suoran leikkauspiste y-akselin kanssa sama. Jos molemmat suorat ovat yhdensuuntaisia y-akselin kanssa, jälkimmäinen funktio tarkistaa, onko niiden leikkauspiste x-akselin kanssa sama.

Tarkastellaan funktiota, joka tarkistaa, onko kahden suoran kulmakertoimet samat. Funktio saa parametrinaan ensimmäisen suoran \(x\):n ja \(y\):n kertoimet (xkerroin1 ja ykerroin1) sekä vastaavat toisen suoran kertoimet (xkerroin2 ja ykerroin2). Suorien yhtälössä esiintyvällä vakiolla ei ole merkitystä kulmakertoimia laskettaessa. Ensimmäisen suoran kulmakerroin on nyt xkerroin1 / ykerroin1. Kulmakertointen yhtäsuuruuden tutkiminen lausekkeella xkerroin1 / ykerroin1 == xkerroin2 / ykerroin2 ei kuitenkaan ole järkevää, koska pyöristysvirheiden takia jakolaskujen tuloksissa voi olla pieni ero, vaikka kulmakertoimet oikeasti olisivatkin samoja.

Yksi vaihtoehto olisi sieventää kulmakertoimet murtolukuina, mutta sievennykseltä säästytään, jos tutkitaan tuloja xkerroin1 * ykerroin2 ja xkerroin2 * ykerroin1. Jos ne ovat yhtäsuuret, myös suorien kulmakertoimet ovat yhtäsuuret, vaikka kulmakertoimia kuvaavat murtoluvut eivät olisikaan sievennetyssä muodossa. Funktio siis tutkii näiden tulojen yhtäsuuruutta ja palauttaa arvon True, jos tulot ovat yhtäsuuria ja muuten arvon False.

Kirjoitetaan funktio, joka saa parametrina kahden suoran yhtälöiden \(x\):n ja \(y\):n kertoimet ja tarkistaa, onko suoriten kulmakerroin sama. Funktio palauttaa arvon True, jos kulmakerroin on sama ja arvon False, jos suorilla on eri kulmakerroin:

def sama_kulmakerroin(xkerroin1, ykerroin1, xkerroin2, ykerroin2):
    if (xkerroin1 * ykerroin2 == xkerroin2 * ykerroin1):
        return True
    else:
        return False

Katsotaan seuraavaksi, miten funktion paluuarvoa voi käyttää pääohjelmassa. Funktion paluuarvo on siis True tai False ja sitä voi käyttää if-käskyn ehdossa esimerkiksi seuraavasti:

if sama_kulmakerroin(eka_a, eka_b, toka_a, toka_b) == True:

Ehdossa oleva yhtäsuuruusvertailu arvoon True on kuitenkin tarpeeton, sillä funktion paluuarvo on jo itsessään tosi tai epätosi, jolloin sitä voidaan käyttää suoraan if-käskyn ehtona seuraavasti:

if sama_kulmakerroin(eka_a, eka_b, toka_a, toka_b):

Tällöin if-käskyyn kuuluvat käskyt suoritetaan, jos funktion sama_kulmakerroin paluuarvo on True, ja jätetään suorittamatta, jos funktion paluuarvo on False.

Jos taas halutaan tehdä if-käsky, johon kuuluvat käskyt suoritetaan silloin kun funktio palauttaa arvon False, voidaan tämä tehdä not-operaattorin avulla:

if not sama_kulmakerroin(eka_a, eka_b, toka_a, toka_b):

Tässä if-käskyn ehto on tosi aina, kun funktion sama_kulmakerroin paluuarvo on False.

Seuraavaksi koko suorien leikkauspisteen laskeva ohjelma. Aikaisemmin kuvatun funktion sama_kulmakerroin lisäksi ohjelmaan on määritelty funktiot sama_akselileikkaus, joka tutkii, leikkaavatko yhdensuuntaiset suorat y-akselin (y-akselin suuntaiset suorat x-akselin) samassa pisteessä, laske_leikkaus, joka laskee suorien leikkauspisteen, sekä pyyda_suora, joka pyytää yhden suoran kertoimet. Merkki \ pääohjelman kahden rivin lopussa kertoo Python-tulkille, että rivi jatkuu seuraavalla rivillä.

Yksinkertaisuuden vuoksi ohjelma ei tarkista, että sille on todella annettu suoran yhtälö. Ohjelma ei siis toimi oikein silloin, jos sille annetaan “suoran” yhtälö, jossa sekä \(x\):n että \(y\):n kertoimet ovat nollia.

def sama_kulmakerroin(xkerroin1, ykerroin1, xkerroin2, ykerroin2):
    if xkerroin1 * ykerroin2 == xkerroin2 * ykerroin1:
        return True
    else:
        return False


def sama_akselileikkaus(a1, b1, c1, a2, b2, c2):
    if b1 == 0 and b2 == 0:  # suorat y-akselin suuntaiset
        if a1 * c2 == a2 * c1:
            return True
        else:
            return False
    elif b1 * c2 == b2 * c1:
        return True
    else:
        return False


def laske_leikkaus(a1, b1, c1, a2, b2, c2):
    yleikkaus = (a1 * c2 - a2 * c1) / (b1 * a2 - b2 * a1)
    if a1 == 0:
        xleikkaus = (-b2 * yleikkaus - c2) / a2
    else:
        xleikkaus = (-b1 * yleikkaus - c1) / a1
    return xleikkaus, yleikkaus


def pyyda_suora():
    print("Anna suoran yhtalo")
    a = int(input("Anna x:n kerroin: "))
    b = int(input("Anna y:n kerroin: "))
    c = int(input("Anna vakio: "))
    return a, b, c


def main():
    print("Etsitaan kahden suoran ax + by + c leikkauspiste")
    eka_a, eka_b, eka_c = pyyda_suora()
    toka_a, toka_b, toka_c = pyyda_suora()
    if sama_kulmakerroin(eka_a, eka_b, toka_a, toka_b) and \
           sama_akselileikkaus(eka_a, eka_b, eka_c, toka_a, toka_b, toka_c):
        print("Suorat ovat yhtenevat koko pituudeltaan.")
    elif sama_kulmakerroin(eka_a, eka_b, toka_a, toka_b):
        print("Suorat ovat yhdensuuntaiset, ei leikkauspistetta.")
    else:
        x_koord, y_koord = laske_leikkaus(eka_a, eka_b, eka_c,\
                                          toka_a, toka_b, toka_c)
        print(f"Leikkauspiste on ({x_koord:.2f}, {y_koord:.2f})")


main()