Kokonaisluku (tietotekniikka)

Wikipediasta
Siirry navigaatioon Siirry hakuun

Kokonaisluku on tietotekniikassa yksi tietotyypeistä. Kokonaisluku tietotyyppinä antaa tulkinnan tietokoneen muistissa oleville bittijonoille. Jos muuttujan viittaama tieto on staattisesti tyypitetty, se ei saa viitata muunkaltaiseen tietoon.

Kokonaisluvut yleisesti ohjelmointikielissä

[muokkaa | muokkaa wikitekstiä]

Ohjelmointikielissä voidaan antaa muuttujan määrittävä lause:[1]

int abc = 42;

Tässä abc on muuttujan nimi eli tunnus, int on muuttujan abc tyyppi ja literaali 42 on muuttujaan sijoitettava arvo.[1] Ohjelmointikielen kääntäjä antaa virheen, jos muuttujaan yritetään sijoittaa jotain mitä tyyppijärjestelmän mukaan siihen ei voida sijoittaa. Muuttuja abc luo symbolisen tietovaraston, josta tietoa voidaan hakea ja johon tietoa voidaan kirjoittaa.

Esimerkkejä int literaaleista ovat:

  • 42
  • 10000
  • -233000

Negatiiviset luvut esitetään tyypillisesti käyttäen kahden komplementtia. Tässä esityksessä nollalle on vain yksi esitystapa ja negatiivisia lukuja on yksi enemmän kuin positiivisia.

C-kielen kokonaisluvut

[muokkaa | muokkaa wikitekstiä]

C-ohjelmointikielessä tuntee viisi etumerkillistä kokonaislukutyyppiä ja niitä vastaavat etumerkittömät kokonaislukutyypit. Näihin on mahdollista viitata eri avainsanojen yhdistelmillä. Lisäksi standardi mahdollistaa toteuttaa lisätyyppejä.[2] Varhainen C-kielen määritelmä ei määrännyt muuttujien kokoa bitteinä, joka määrää niiden suurimmat tallennettavan luvun tai arvoalueen. Standardin versiosta C99 on muuttujille määrätty vähimmäiskoot.[3][4]

  • (unsigned) char on vähintään 8 bittiä , [0, 255]
  • signed char, 8 bittiä, [−128, 127]
  • (signed) short int, 16 bittiä, [−32,768, +32,767]
  • unsigned short int, 16 bittiä, [0, 65,535]
  • (signed) int, 16 bittiä, [−32,768, +32,767]
  • unsigned int, 16 bittiä, [0, 65,535]
  • (signed) long int, 32 bittiä, [−2,147,483,648, +2,147,483,647]
  • unsigned long int, 32 bittiä, [0, 4,294,967,295]
long long
  • (signed) long long int, 64 bittiä, [−9,223,372,036,854,775,808, +9,223,372,036,854,775,807] (C99-standardi)
  • unsigned long long int, 64 bittiä, [0, 18,446,744,073,709,551,615] (C99-standardi)

Huomaa, että alustasta ja ympäristöstä riippuen kokonaisluvut voivat käyttää eri kokoja. Näitä ovat esimerkiksi ILP32- ja LP64-mallit, joissa int, long ja osoitin voivat käyttää eri kokoja.[5]

Kokonaisluvut binäärilukuina

[muokkaa | muokkaa wikitekstiä]

Java 7:n int on oletusarvoisesti etumerkillinen 32-bittinen kokonaisluku.

  • 0000 0000 0000 0000 0000 0000 0000 0000 vastaa 0;
  • 0111 1111 1111 1111 1111 1111 1111 1111 vastaa 2 147 483 647 (2ˆ31−1);
  • 1000 0000 0000 0000 0000 0000 0000 0000 vastaa -2 147 483 648 (−(2ˆ32));
  • 1111 1111 1111 1111 1111 1111 1111 1111 vastaa -1.

Riippuen valitusta kokonaislukutyypistä sitä vastaa erikokoinen binääriluku. Esimerkiksi kokonaisluku 45 varataan tietokoneen muistiin kyseisillä eri binääriluvuilla:

  • Jos kokonaislukutyyppi on byte: 0010 1101 (8 bittiä)
  • Jos kokonaislukutyyppi on short: 0000 0000 0010 1101 (16 bittiä)
  • Jos kokonaislukutyyppi on int: 0000 0000 0000 0000 0000 0000 0010 1101 (32 bittiä)
  • Jos kokonaislukutyyppi on long: 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0010 1101 (64 bittiä)

[6]

Implisiittiset kokonaisluvut

[muokkaa | muokkaa wikitekstiä]

C99 vaatii toteutusta antamaan diagnostiikan kun tietotyyppinä on implisiittisesti kokonaislukutyyppi int.[7] Esimerkiksi ennen C99:ää voi olla:[7]

extern x;
f(y)
{
    register z = g(x) + y;
    return z;
}

.. jossa x, y ja z käsiteltiin tyyppinä int.[7]

Kokonaisluvun ylivuoto ja ympäripyörähtäminen

[muokkaa | muokkaa wikitekstiä]

Kokonaislukujen käsittelyssä on kaksi tapahtumaa, joista toisinaan molempiin viitataan ylivuotona. Täsmällisesti sanottuna aritmeettinen ylivuoto pätee vain etumerkillisiin (signed) ja osoitintyyppeihin, ja on määrittelemätön toiminto. Ympäripyörähtäminen on etumerkittömille (unsigned) tietotyypeille. Ympäripyörähtämisessä arvo palaa luotettavasti nollaan. Historiallisesti on sallittu myös yhden komplementti, mutta nykyisin voi olettaa käytössä olevan kahden komplementti.[8][9] C-kielen standardissa ylivuoto on määrittelemätön, jonka vuoksi ylivuodot muutetaan määritellyiksi ympäripyörähtämisiksi.[10]

Epäonnistuneet aritmeettiset operaatiot

[muokkaa | muokkaa wikitekstiä]

Etumerkittömän (unsigned) aritmeettisen operaation ylivuototapauksissa ongelma ratkeaa modulo-operaationa, joka säilyttää vähiten tärkeät bitit. Kahden kokonaisluvun yhteen- tai kertolaskussa tulos voi olla yllättävän pieni ja pienestä kokonaisluvusta vähentäminen voi kääntyä suureksi positiiviseksi arvoksi. Esimerkiksi 8 bitin kokonaisluvun 255 + 2 tuottaa tulokseksi 1, joka on 257 mod 28. Vähennyslasku 0 − 1 tuottaa tulokseksi 255, joka vastaa kahden komplementtina arvoa −1.

Arvoalueen maksimisuuruus ylitetty

[muokkaa | muokkaa wikitekstiä]
Etumerkillinen kokonaisluku

Kokonaisluvun ylivuoto tapahtuu kun aritmeettinen operaatio pyrkii tuottamaan etumerkillisen (signed) kokonaislukuarvon, joka ylittää tai alittaa määritellyn lukualueen maksimisuuruuden. 8-bittinen kokonaisluku 127 + 1 tuottaa tulokseksi −128, joka on kahden komplementti luvusta 128. Ongelman voi kiertää käyttämällä etumerkitöntä (unsigned) tyyppiä kun arvot eivät tule koskaan olemaan negatiivisia (8-bittiselle kokonaisluvulle arvot välillä 0 ja 255), tai käyttämällä suurempaa tyyppiä (kasvattamalla 8-bittinen kokonaisluku 16-bittiseksi).

Liian suuren arvon alustaminen

Kun muuttujalle varattuun muistipaikkaan yritetään alustaa maksimisuuruuden ylittävä arvo, kääntäjä leikkaa muistin ylivuodon välttämiseksi ylimääräiset siihen mahtumattomat bitit. Esimerkiksi kokonaisluku 1234 on binäärilukuna 10011010010 (11 bittiä) ja kun se sovitetaan 8 bittiin, siitä kääntäjä leikkaa ylimääräiset kolme bittiä (100). Tuloksena on kahden komplementtina tulkittu kokonaisluku -46.[11]

Muunnokset kokonaislukujen ja liukulukujen välillä

[muokkaa | muokkaa wikitekstiä]

Myös muunnoksissa liukuluvuista kokonaislukuihin voi tapahtua virheitä.[12]

  1. a b Glenn G. Chappell: CS 331 Spring 2018 A Primer on Type Systems cs.uaf.edu. Viitattu 22.2.2020. (englanniksi)
  2. ISO/IEC 9899:TC3 § 6.2.5 Types
  3. ISO/IEC 9899:TC3 § 5.2.4.2.1 Sizes of integer types <limits.h>
  4. Committee Draft (PDF) open-std.org. 7.9.2007. Viitattu 4.2.2024. (englanniksi)
  5. ILP32 and LP64 data models and data type sizes ibm.com. Viitattu 4.2.2024. (englanniksi)
  6. https://medium.com/@wandercosta/twos-complement-7e6c5d8c14c1
  7. a b c Randy Meyers: The New C: Integers in C99, Part 1 1.12.2000. Dr. Dobb's. Arkistoitu Viitattu 19.6.2019. (englanniksi)
  8. Kees Cook: [PATCH 00/82 overflow: Refactor open-coded arithmetic wrap-around] lwn.net. 22.1.2024. Viitattu 4.2.2024. (englanniksi)
  9. Basics of Integer Overflow gnu.org. Viitattu 4.2.2024. (englanniksi)
  10. Jonathan Corbet: Better handling of integer wraparound in the kernel lwn.net. 26.1.2024. Viitattu 1.4.2024. (englanniksi)
  11. https://lovelace.oulu.fi/tietokonej%C3%A4rjestelm%C3%A4t/tietokonej%C3%A4rjestelm%C3%A4t-syksy-2022/muuttujat-c-kieless%C3%A4/
  12. Numerical computations with IEEE arithmetic (PDF) cs.nyu.edu. Viitattu 4.2.2024. (englanniksi)