CMD + K

Informasjonsteknologi grunnkursVariabler, datatyper og tallrepresentasjonBegreper & formler8
7 min lesing1 video

Variabler, datatyper og tallrepresentasjon

En variabel er et navn som peker på en verdi i minnet. Python skiller mellom datatyper som int, float, str og bool, og du kan konvertere mellom dem. Vi ser også hvorfor flyttall gir avrundingsfeil og hvordan tall representeres i maskinen.

Læringsmål
  • 01Forklare hva en variabel er, og at tilordning med = legger en verdi inn i et navngitt minneområde
  • 02Skille mellom datatypene int, float, str og bool, og avgjøre hvilken type en gitt verdi har
  • 03Forklare hvorfor flyttall lagres med fortegn, eksponent og mantisse, og hvordan det fører til avrundingsfeil
  • 04Bruke typekonvertering med int(), float() og str(), og forklare hvorfor inndata fra brukeren alltid må konverteres fra streng

En navngitt eske å legge ting i

Tenk på en garderobe med nummererte skap. Du legger noe i skap 17, men du gidder ikke å huske «17» — du henger på en lapp der det står «treningstøy». Neste gang henter du bare det som ligger «i treningstøy», uten å bry deg om skapnummeret. En variabel fungerer akkurat slik. Det er et navn du gir til en plass i maskinens minne, og navnet lar deg legge inn en verdi, hente den fram igjen, og bytte den ut senere.

I Python lager du en variabel ved å gi den et navn og en verdi:

python
alder = 25 navn = "Kari"

Her peker alder til verdien 25 og navn til teksten Kari. Tegnet = betyr ikke «er lik» slik som i matematikk; det betyr «legg verdien til høyre inn i variabelen til venstre». Det er en tilordning, en handling. Derfor gir alder = alder + 1 god mening i kode selv om det ville vært tøv i matematikk: regn ut det som står til høyre (25 + 1), og legg resultatet (26) tilbake i alder.

Et godt variabelnavn forteller hva verdien betyr. x sier ingenting; antall_studenter sier alt. Du skriver kode én gang, men leser den mange ganger — ofte er det ditt eget framtidige jeg som leser. Vær raus med beskrivende navn.

Noen regler gjelder for hva et navn kan være. Det må begynne med en bokstav eller understrek, kan inneholde tall etter det, men ikke mellomrom — derfor skriver vi antall_studenter med understrek i stedet for et ellers naturlig mellomrom. Navnet skiller dessuten mellom store og små bokstaver: Alder og alder er to forskjellige variabler. Og det er forskjell på en variabel og verdien i den. Variabelen er lappen på skapet; verdien er det som ligger i skapet akkurat nå. Du kan bytte ut innholdet uten å bytte lapp, og det er nettopp det som gjør variabler nyttige: de holder styr på noe som endrer seg mens programmet kjører, som en poengsum eller en gjenstående saldo.

Datatyper: hva slags verdi er det?

Hver verdi i Python har en datatype som bestemmer hva verdien er og hva du kan gjøre med den. Fire grunntyper bærer det meste i starten.

En heltall (int) er et heltall: 0, 42, -7. Heltall har ingen desimaler og kan i Python bli så store du vil uten å «renne over».

En flyttall (float) er et flyttall, altså et desimaltall: 3.14, -0.5, 2.0. Merk at 2 og 2.0 er ulike typer selv om de tallmessig er like — den første er en int, den andre en float. Desimaltegnet er punktum, ikke komma, i Python.

En streng (str) (string) er tekst: "Kari", "42", "a". Tekst omsluttes av anførselstegn. Legg merke til at "42" er en streng, ikke et tall — det er tre tegn, ikke verdien førtito. Det er en kilde til mye forvirring, og vi kommer tilbake til det.

En boolsk verdi (bool) er en sannhetsverdi og har bare to mulige verdier: True og False. Boolske verdier driver alle valg et program tar, og får et helt kapittel for seg selv senere.

Du kan alltid spørre Python hvilken type en verdi har:

python
print(type(25)) # <class 'int'> print(type(3.14)) # <class 'float'> print(type("Kari")) # <class 'str'> print(type(True)) # <class 'bool'>

Hvordan tall faktisk lagres

Inni maskinen finnes verken sifre eller bokstaver — bare bits, som hver er enten 0 eller 1. En bit er den minste informasjonsenheten, som en lysbryter som står av eller på. Alt må til slutt uttrykkes i slike bits. Et heltall lagres som et binærtall: en rekke bits som til sammen koder en eksakt verdi. På samme måte som vi i titallssystemet bygger tall av posisjoner verdt 1, 10, 100 og så videre, bygger binærtallet verdier av posisjoner verdt 1, 2, 4, 8 og oppover. Tallet fem skrives 101 i binær: én firer, ingen toer, én ener. Du trenger ikke å regne om i hodet til daglig, men poenget er at heltall lar seg lagre helt eksakt — det finnes ingen «mellomverdi» som faller mellom to bit-mønstre. Et desimaltall lagres derimot på en mer sammensatt måte, og det er her det blir interessant.

En float lagres i et format som deler opp bitene i tre felt.

64-bit flyttall (double)6306352Fortegn · + eller - · 1 bit1 bitEksponent · hvor komma står · 11 bit11 bitMantisse · selve sifrene · 52 bitMantisse52 bitselve sifreneFast antall bits per felt gir et tak på presisjonen, og dermed avrundingsfeil.
FIGSlik lagres en float (64 bit)

Det første feltet er ett fortegnsbit (pluss eller minus). Det neste er en eksponent, som forteller hvor «komma» skal stå — på samme måte som i 1.5 · 10³, bare med 2 som grunntall. Det siste og største feltet er mantissen (også kalt signifikanden), som holder selve sifrene i tallet. Tre felt, fast antall bits hver, og dermed et tak på hvor presist et tall kan beskrives.

Den faste størrelsen er nettopp problemet. Med et endelig antall bits i mantissen kan du bare lagre et endelig antall ulike verdier. De fleste desimaltall passer ikke eksakt inn, like lite som 1/3 passer eksakt inn som et endelig desimaltall (0.3333…). Maskinen lagrer da den nærmeste verdien den klarer, og den lille forskjellen kaller vi avrundingsfeil.

Når 0.1 + 0.2 ikke blir 0.3

Det mest berømte eksempelet:

python
print(0.1 + 0.2) # 0.30000000000000004

Dette er ingen feil i Python — det skjer i nesten alle programmeringsspråk, av samme grunn. Verken 0.1 eller 0.2 kan lagres eksakt som binære flyttall, så summen bommer på 0.3 med et bittelite beløp. Tenk på det som å måle med en linjal som bare har streker for hver halve millimeter: du kan komme veldig nær, men noen lengder treffer aldri en strek nøyaktig.

0.290.30.310.3 (ønsket)0.1 + 0.2 (lagret)0.1 + 0.2 lander en bitteliten bit over 0.3 fordi tallene ikke kan lagres eksakt binært.
FIGLagret verdi treffer ikke 0.3 nøyaktig

Konsekvensen er praktisk og viktig: sammenlign aldri to flyttall med == og forvent at de er nøyaktig like. I stedet sjekker du om de er nær nok hverandre. Og når du skal vise et resultat til en bruker, runder du av til et fornuftig antall desimaler.

Det betyr ikke at flyttall er ubrukelige — tvert imot er de uunnværlige for alt fra fysikkberegninger til økonomi. Du må bare vite hva slags verktøy du har i hånda. Heltall er eksakte, men kan ikke representere noe mellom to hele tall. Flyttall dekker hele tall-aksen med desimaler, men til en pris: en bitteliten unøyaktighet du må ta høyde for. Når du regner med penger og hver øre teller, finnes det egne, mer nøyaktige tilnærminger, men i de fleste sammenhenger i dette emnet er vanlig flyttall mer enn presist nok — så lenge du husker å ikke kreve eksakt likhet.

Typekonvertering: å bytte drakt på en verdi

Ofte har du en verdi av én type, men trenger den som en annen. Når du leser inn noe fra brukeren, kommer det alltid som en streng — selv om brukeren skrev et tall. Skriver de 42, får programmet teksten "42", ikke verdien 42. Prøver du å regne med en slik streng, går det galt. Løsningen er typekonvertering: du ber Python lage en ny verdi av ønsket type ut fra den du har.

typekonvertering

Konverter mellom typer

python
tekst = "42"tall = int(tekst)        # tall er nå heltallet 42print(tall + 8)          # 50 desimal = float("3.14")  # desimal er flyttallet 3.14print(int(3.9))          # 3  — int() kutter desimalene, runder ikke alder = 25melding = "Alder: " + str(alder)   # gjør tallet om til tekst for å slå sammenprint(melding)           # Alder: 25

int(), float() og str() lager en ny verdi av ønsket type. Strengen må se ut som et tall for at int() og float() skal lykkes, og int() kutter desimaler i stedet for å runde av.

Funksjonen int(...) lager et heltall, float(...) lager et flyttall, og str(...) lager en streng. Vær oppmerksom på to fallgruver. For det første kaster int() bort desimalene i stedet for å runde: int(3.9) blir 3, ikke 4. For det andre må strengen faktisk se ut som et tall — int("hei") gir en feil, fordi det ikke finnes noe heltall å lage av bokstaver.

Sett det sammen

En variabel er et navn på en plass i minnet der en verdi bor. Verdien har en datatype — int for heltall, float for desimaltall, str for tekst og bool for sant/usant — som bestemmer hva du kan gjøre med den. Tall lagres til slutt som bits, og fordi flyttall har et fast antall bits, oppstår avrundingsfeil som gjør at du aldri bør sammenligne to floats med streng likhet. Og fordi inndata alltid kommer som tekst, må du ofte konvertere mellom typer med int(), float() og str() for å få regnet riktig. Disse grepene er bygningssteinene under alt du programmerer videre.

Mine notater

Skriv egne notater for dette kapittelet. De lagres automatisk og dukker opp i «Mine notater»-oversikten paa fag-siden.

Laster…