Tietotyypit ja operaattorit Luennossa tarkastellaan yksinkertaisten tietotyyppien int, double ja char muunnoksia tyypistä toiseen sekä esitellään uusia operaatioita. Numeeriset tietotyypit ja muunnos Merkkitieto ja muunnos Loogiset lausekkeet Arvon kasvattaminen (inkrementointi) ja ja vähentäminen (dekrementointi) 273
Numeeriset tietotyypit ja muunnos Tehokkuussyistä C-kielessä on erilaisia tietotyyppejä numeeriselle tiedolle. tavalliset kokonaisluvut loogiset arvot ja silmukan laskurit 274
Kokonais- ja reaalilukujen sisäiset esitykset tietokoneen muistissa binäärilukuina (2-järjestelmän lukuina) ovat erilaiset: kokonaisluku muutetaan suoraan binääriluvuksi esim. luku +12 10 binäärilukuna (32-bittisenä) on: 0000 0000 0000 0000 0000 0000 0000 1100 2 Esimerkiksi kokonaislukujen vaihteluväli -2147483648 ja 2147483647 luvut voidaan esittää tällä välillä tarkasti käyttämällä kokonaislukutyyppiä int. 275
Reaaliluku muodostuu osista mantissa ja eksponentti, mantissa ja eksponentti talletetaan binäärilukuina. Reaalilukujen käsittelyssä olennaista esitysvirheet ja epätarkkuus alivuoto, luku liian lähellä nollaa ylivuoto, luku liian suuri luvun sisäisessä esityksessä pyöristysvirheet: 276
#include <stdio.h> int main(void){ double result = 0.0; result = 0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1; printf("result: %.25lf\n", result); return 0; } 277
278
reaalilukujen yhtäsuuruuden suoraa vertailua tulisi välttää, sillä esimerkiksi: #include <stdio.h> int main(void){ if((1.2-0.1) == 1.1) printf("\n1.2-0.1 on todellakin 1.1\n"); else printf("\n1.2-0.1 on ohjelmassa %.16lf\n", (1.2-0.1)); } return(0); 279
Kokonaislukuesitys vaatii vähemmän muistia ja yleensä kokonaislukuoperaatiot ovat tehokkaampia. 280
Kokonaislukutietotyypit C-kielessä: Tyyppi Arvoalue ( minimiarvoja, saattaa vaihdella) short -32 768 32 767 unsigned short 0... 65 535 int -32 768 32 767 unsigned 0 65 535 long -2147483648... 2147483647 unsigned long 0 4294967295 281
Reaalilukutyypit C-kielessä: Tyyppi Arvoalue merkitsevät numerot float 10-37... 10 38 6 double 10-307 10 308 15 long double 10-4931 10 4932 19 282
Tietotyyppien automaattinen muunnos tietotyypistä toiseen: int k=5, m=4, n; double x=1.5, y=2.1,z; Tapaus lauseke jossa binaarioperaattori ja erityyppiset operandit sijoituslause jossa kohdemuuttuja double ja lauseke Esimerkki Selitys k * x int muuttujan k arvo muutetaan tyypiksi double ennen operaatiota z = k + m Ensin lausekkeen arvo sitten muunnos ja sijoitus sijoituslause jossa kohdemuuttuja int ja lauseke double n = x * y Ensin lausekkeen arvo sitten muunnos ja sijoitus 283
Muunnos todellisen ja muodollisen parametrin välillä funktioiden yhteydessä samoin kuin sijoituslauseella. C-kielessä on myös eksplisiittinen (näkyvä) muunnosoperaatio (type casting), joka saadaan asettamalla muunnettavan lausekkeen eteen sulkuihin uusi tietotyyppi. Esimerkki: Oletetaan, että muuttujat aineidensumma ja aineidenlkm ovat kokonaislukutyyppiä. Seuraavassa jakolaskussa menetetään desimaaliosa keskiarvo = aineidensumma / aineidenlkm; 284
Käyttämällä tietotyypin muunnosta seuraavaan tyyliin desimaaliosa voidaan pelastaa keskiarvo = (double)aineidensumma / (double)aineidenlkm; 285
On myös helppo tehdä virheitä keskiarvo = (double)(aineidensumma / aineidenlkm ); Oletuksena, että keskiarvo on tyyppiä double. 286
#include <stdio.h> #define LOPPU -1 int main(void){ int arvosana=0, aineidensumma=0, aineidenlkm=0; double keskiarvo=0.0; printf("\nanna arvosana >"); scanf("%d", &arvosana); while(arvosana!= LOPPU){ } aineidensumma = aineidensumma + arvosana; aineidenlkm = aineidenlkm + 1; printf("\nanna arvosana >"); scanf("%d", &arvosana); 287
keskiarvo = (double)aineidensumma / (double)aineidenlkm; printf("\naineiden keskiarvo on %5.2lf", keskiarvo); printf("\n\n"); return(0); } 288
289
Muunnos ei muuta muuttujan sisältöä pysyvästi #include <stdio.h> #define LOPPU -1 int main(void){ int x; x = 5; printf ("%lf\n", (double) x); printf("%d\n", x); } return(0); 290
291
Merkkitieto ja muunnos Tietotyyppi char yksittäisten merkkien käsittelyyn. #define STAR '*' char kirjain; kirjain = 'A'; Merkkitietoa voidaan vertailla samaan tyylin kuin numerotietoa. Esim. jos muuttujat merkki1 ja merkki2 ovat tyyppiä char, niin seuraavat vertailut ovat mahdollisia: merkki1!= merkki2; merkki1 > merkki2; 292
Jokaisella tulostettavalla merkillä on numerokoodi (kokonaisluku), joka esitetään binäärimuodossa tietokoneen muistissa (ASCII koodi): merkkien '0' - '9' koodit ovat 48-57 isot kirjaimet 'A' - 'Z' on koodattu 65-90 pienet kirjaimet 'a' - 'z' on koodattu 97-122 Huom! ns. skandit Å, å, Ä, ä, Ö, ö! 293
Koska merkit koodattu kokonaislukuina on muunnos kokonaisluvuksi mahdollista. char merkki = 'A'; /* luku 65 */ merkki = merkki +1; /* nyt merkki sisältää merkin 'B' koodin */ 294
Merkin kokonaislukuarvo saadaan muunnosoperaattorilla: #include <stdio.h> int main(void){ int koodi; char merkki = 'A'; merkki = merkki + 1; koodi = (int) merkki; printf("\nmerkin \'%c\' koodi on %d\n", merkki, koodi); } return(0); 295
Ohjelma tulostaa: 296
Loogiset lausekkeet C-kielessä loogiset tietotyypit tosi ja epätosi esitetään kokonaislukuina. Arvoa tosi vastaa 1 ja arvoa epätosi luku 0. Loogisten lausekkeiden yhdistämien. if (10 < x < 100) /* EI NÄIN */ 297
Loogisten lauseiden yhdistämiseen operaattorit && (looginen JA), (looginen TAI) ja! (looginen NEGAATIO) JA-operaattorin totuustaulukko: operandi1 operandi2 && 1 1 1 1 0 0 0 1 0 0 0 0 298
TAI-operaattorin totuustaulukko: operandi1 operandi2 1 1 1 1 0 1 0 1 1 0 0 0!-operaattorin totuustaulukko arvo! 1 0 0 1 299
Seuraavassa esimerkkejä loogisista lausekkeista (ehtolausekkeista) ja niiden suorituksesta. Oletetaan että x, y ja z ovat tyyppiä double ja lippu on tyyppiä int sekä muuttujilla arvot x=3.0, y=4.0, z=2.0 ja lippu=0. 300
Lauseke Arvo x > z && y > z 1 x + y / z <= 3.5 0 z > x z > y 0!lippu 1 x == 1.0 x == 3.0 1 z < x && y + z >= x - z 1!lippu y + z >= x - z 1!(lippu y + z >= x - z) 0 301
Operaattoreiden sidontajarjestys määrää lausekkeiden laskentajärjestyksen: suoritusjärjestys suuurin operaatio funktiokutsut! + - (ns. unaarit) & * tyypin muunnokset * / % + - (binäärit) < > <= >= ==!= && viimeiseksi = 302
vastaus = 2 + (int)ceil(80.2) % 9 > 10; 81.0 81 0 2 0 0 303
Loogisia lausekkeita mahdollista käytää myös sijoituslauseissa: #include <stdio.h> int main(void){ int onkirjain; char merkki; printf("\nsyota jokin merkki >"); scanf("%c", &merkki); onkirjain = ('A' <= merkki && merkki <= 'Z') ('a' <= merkki && merkki <= 'z'); 304
if(onkirjain) printf("\nsyöttämäsi merkki on on aakkonen\n"); else printf("\nmerkki \'%c\' ei ole iso eikä pieni kirjain\n", merkki); } return(0); 305
306
Inkrementointi ja dekrementointi Inkrementointioperaattori (kasvattaa arvoa) tähän tehtävän operaattori ++ aiheuttaa operandin arvon kasvattamisen yhdellä. Esim. for(laskuri = 0; laskuri < RAJA; laskuri++) 307
Voidaan käyttä sekä lauseena että lausekkeena. Lausekkeena arvo määräytyy operaattorin sijainnin mukaan ++i tai i++ Ennen: i j 2 0 Inkrementointi j= ++i; j= i++; kasvata i:n käytä i:tä ja arvoa ja käytä kasvata sen jälkeen sitä Jälkeen: i j i j 3 3 3 2 308
Yhdistetty sijoituslause muuttuja operaattori = lauseke, jossa operaattori voi olla +, -, *, / tai % Perinteinen sijoituslause Yhdistettynä laskuri = laskuri + 4 laskuri += 4; aika = aika - 10; aika -= 10; netto = netto + palkka; netto += palkka; tulo = tulo * data; tulo *= data; n = n * (x + 1) n *= x + 1; tulos = tulos % (( ylin -40) / 2); tulos %= (( ylin -40) / 2); 309