Lukujen esittäminen desimaali- ja binäärijärjestelmässä, muunnosalgoritmeja lukujärjestelmien välillä sekä kvanttilotto

Tässä artikkelissa kerrataan lukiomatematiikan lähtökohdista binäärijärjestelmän perusteet, ja esitellään lyhyesti algoritmeja miten luvun muuntaminen desimaalijärjestelmän ja binäärijärjestelmän välillä voidaan laskea. Ohjelmointiesimerkit on tehty pythonilla. Ohjelmointiesimerkit toteuttavat samat ideat mitä laskuesimerkeissä havainnollistetaan. Esimerkkien avulla on tarkoitus tukea algoritmisen ajattelun kehittymistä lukiossa.

Artikkelin lopussa esitellään lyhyesti kvanttitietokoneille tehty algoritmi, jossa binäärilukuesityksen avulla arvotaan kvanttitietokoneella lottonumerot väliltä 1- 40. Kvanttialgoritmin ohjelmointi sisältää vaikeampia tietorakenteita.

Binäärijärjestelmässä kantaluku on kaksi

Tavallisessa desimaalijärjestelmässä luvut esitetään kantaluvun $10$ potenssien avulla. Luvun esittämisessä käytettyjen numeroiden $0,1,2 ... 9$ paikka ilmaisee ykkösten, kymppien satojen... eli kantaluvun 10 potenssien lukumäärän. Esimerkiksi desimaalijärjestelmän luku $245$ voidaan hajoittaa muotoon:

$$ 245= 2\cdot 100+ 4 \cdot 10 + 5\cdot 1 = 2\cdot 10^2 + 4\cdot 10^1 + 5\cdot 10^0$$

Binäärijärjestelmän kantaluku on $2$. Binääriluvussa bitin $0$ tai $1$ paikka ilmaisee mikä kantaluvun $2$ potenssi on kysessä. Esimerkiksi desimaalijärjestelmän luku $11_{10}$ saa binäärijärjestelmässä esitysmuodon $1011_2$ , koska

$$11_{10} = 8+2+1 = 1 \cdot 2^3+0 \cdot 2^2 +1\cdot 2^1+1\cdot 2^0 = 1011_2$$

Esimerkiksi binääriluku $11001_2$ voidaan muuttaa desimaalijärjestelmän luvuksi seuraavalla algortimilla:

$$11001_2 = 1\cdot 2^4+ 1\cdot 2^3+0\cdot 2^2+0\cdot 2^1+1\cdot 2^0=16+8+1 = 25_{10}$$

Muunnokset binääriesityksen ja desimaalijärjestelmän välillä pythonissa

Tietokoneiden muistissa kaikki digitaalinen informaatio esitetään bittien avulla, bitin tila voi olla joko $0$ tai $1$. Python-ohjelmointikielessä desimaalijärjestelmän luvun voi muuttaa binääriluvuksi komennolla bin(kokonaisluku). Vastaavasti binääriluvun voi muuttaa desimaalijärjestelmään komennolla int(binääriluku,2). Funktion 2.parametrina annettu luku $2$ ilmaisee, että 1.parametri on binääriluku. Pythonissa etuliite 0b ilmaisee, että kyseessä on binääriluku. Tällöin esimerkiksi print-komento tunnistaa binääriluvun, ja antaa tulosteen desimaalijärjestelmässä. Esimerkkejä:

Algoritmeja lukujärjestelmästä toiseen siirtymiseksi

Binäärijärjestelmästä desimaalijärjestelmään

Seuravaaksi esitellään miten binääriluku $b$ voidaan laskemalla muuttaa desimaalijärjestelmän luvuksi $a$ kahdella erilaisella algoritmilla.

Menetelmässä 1 eli suorassa laskussa binääriluvun bitit $0$ ja $1$ antavat kertoimet kantaluvun $2$ eri potensseille:

$$10111_2= 1\cdot 2^4 +0\cdot 2^3+ 1\cdot 2^2+1\cdot 2^1+1\cdot 2^0 = 16+0+4+2+1 =23_{10}$$

Alla esimerkissä suora laskumenetelmä pythonilla toteutettuna kun binäärilkuku $b$ annetaan aluksi merkkijonona (esim. $0b11010$). Pythonissa potenssi ilmaistaan operaattorilla **. Kun binääriluku on merkkijono, sen sisältämiä bittejä voidaan indeksoida kuin listan alkioita välillä $0 ...len(b)-1$, missä funktion len(b) palauttama arvo ilmaisee merkkijonon pituuden. Esimerkiksi b kirjain on merkkijonossa 0b11010 indeksoitu luvulla 1 ja ykkösten määrän ilmaiseva bitti $0$ indeksin arvolla 6. Nämä merkit saadaan listasta b[] komeinnoilla b[1] ja b[6]. Merkkijonon bitit muunnetaan kokoknaisluvuiksi int() -funktiolla. Kun merkkijono tulkitaan listaksi b[], sen alkioita voidaan käydä läpi for-silmukassa.

Binäärijärjestelmästä desimaalijärjestelmään

Menetelmässä 2 binäääriluku $10111_2$ tulkitaan desimaalijärjestelmän luvuksi ja lasketaan jakojäännöksiä kun luku jaetaan luvulla $10$. Jos jakojäännös tietyn bitin kohdalla on $1$, lisätään desimaalijärjestelmän lukuun tätä bittiä vastaava kantaluvun $2$ potenssi. Kokonaisjakoa käyttämällä piennennetäään lukua kunnes luku on nolla. Muunnetaan binääriluku $10111_2$ desimaalijärjestelmän luvuksi a yllä kuvatun algoritmin mukaisesti:

Alustus: desimaalijärjestelmän luvun $a$ alkuarvo $a=0$.

1.kierros: Kun luku $10111_{10}$ jaetaan luvulla $10$, niin jakojäännös on $1$, eli desimaalijärjestelmän lukuun $a=0$ lisätään $a = 1\cdot 2^0$. Suoritetaan kokonaisjako $10111 : 10 = 1011$.

2.kierros: Kun luku $1011_{10}$ jaetaan luvulla $10$, niin jakojäännös on $1$, eli desimaalijärjestelmän lukuun $a=1$ lisätään luku $a = 1+ 1\cdot 2^1= 3$. Suoritetaan kokonaisjako $1011 : 10 = 101$.

3.kierros: Kun luku $101_{10}$ jaetaan luvulla $10$, niin jakojäännös on $1$, eli desimaalijärjestelmän lukuun $a=3$ lisätään luku $a = 3+ 1\cdot 2^2= 3+4=7$. Suoritetaan kokonaisjako $101 : 10 = 10$.

4.kierros: Kun luku $10_{10}$ jaetaan luvulla $10$, niin jakojäännös on $0$, eli desimaalijärjestelmän lukuun $a=7$ lisätään luku $a = 7+ 0\cdot 2^2= 7$. Suoritetaan kokonaisjako $10 : 10 = 1$.

5.kierros: Kun luku $1_{10}$ jaetaan luvulla $10$, niin jakojäännös on $1$, eli desimaalijärjestelmän lukuun $a=7$ lisätään luku $a = 7+ 1\cdot 2^4= 7 +16 = 23$. Suoritetaan kokonaisjako $1 : 10 = 0$. Algoritmin suoritus loppuu, koska kokonaisjaossa päädyttiin lukuun $0$.

Ohjelmoidaan pythonilla yllä esitetty algoritmi, jolla binääriluku muutetaan kymmenjärjestelmään. Pythonissa operaattori % tarkoittaa jakojäännöksen laskemista, ja operaattori // kokonaisjakoa. Esimerkiksi operaatio 7 % 2 antaa tulokseksi 1 ja lasku 7 // 2 on 3. Määritellään funktio binToInt(b), joka muuttaa syötteenä samaamansa binääriluvun b desimaalijärjestelmän luvuksi. Kutsutaan tämän jälkeen funktiota binToInt ja muutetaan binääriluku $11010_2$ desimaalijärjestelmän luvuksi $26$.

desimaalijärjestelmästä binäärijärjestelmään

Seuravaaksi esitellään algoritmi miten desimaalijärjestelmän luku $a$ muutetaan binääriluvuksi $b$. Binääriluvun alkuarvoksi asetetaan nolla, eli $b =0$. Menetelmässä tutkitaan jakojäännöksiä kun desimaalijärjestelmän luku jaetaan binäärijärjestelmän kantaluvulla $2$. Jakojäännös $0$ tai $1$ lisätään binäärilukuun siihen kohtaan, minkä kantaluvun $10$ potenssi ilmaisee. Muutetaan esimerkkinä luku $23_{10}$ binääriluvuksi $b$:

Alkuaskel $b =0_2$.

1.kierros: Kun luku $23_{10}$ jaetaan luvulla $2$, niin jakojäännös on $1$, eli lisätään bitti binääärilukuun $b=0 + 1\cdot 10^0 = 1_2$. Suoritetaan kokonaisjako $23 : 2 = 11_{10}$.

2.kierros: Kun luku $11_{10}$ jaetaan luvulla $2$, niin jakojäännös on $1$, eli lisätään bitti binääärilukuun $b=1 + 1\cdot 10^1 = 11_2$. Suoritetaan kokonaisjako $11 : 2 = 5_{10}$.

3.kierros: Kun luku $5_{10}$ jaetaan luvulla $2$, niin jakojäännös on $1$, eli lisätään bitti binääärilukuun $b=11 + 1\cdot 10^2 = 111_2$. Suoritetaan kokonaisjako $5 : 2 = 2_{10}$.

4.kierros: Kun luku $2_{10}$ jaetaan luvulla $2$, niin jakojäännös on $0$, eli lisätään bitti binääärilukuun $b=111 + 0\cdot 10^3 = 0111_2$. Suoritetaan kokonaisjako $2 : 2 = 1_{10}$.

5.kierros: Kun luku $1_{10}$ jaetaan luvulla $2$, niin jakojäännös on $1$, eli lisätään bitti binääärilukuun $b=0111 + 1\cdot 10^4 = 1011_2$. Suoritetaan kokonaisjako $1 : 2 = 0_{10}$. Algoritmin suoritus päättyy.

Alla sama algoritmi on kirjoitettu funktioksi IntToBinary(a), jolla parametrina annettu desimaalijärjestelmän luku voidaan muuttaa binääriluvuksi. Kutsutaan funktiota parametrin arvolla 23.

Kvanttialgoritmi lottonumeroiden arvontaan

Kvanttitietokoneiden muistissa informaatio on esitetty klassisten bittien sijasta kubittien avulla. Yhden kubitin tila voi olla samanaikaisesti molempien tilojen 0 ja 1 yhdistelmä eli superpositio.

$$ \mid\psi> = a\mid0>+b\mid1> $$

Kubitin tilaa havainnollistetaan usein ns. Blochin pallon pinnalle päättyvänä vektorina. Porttien H, X, Y tai Z-kvanttiporttien operaatiot ovat kubittivektorin kiertoja tämän pallon pinnalla. Kun kubittiin operoidaan esimerkiksi kvanttiportilla H, niin päädytään tilanteeseen, jossa yhden kubitin tila on samanaikaisesti olla tilojen 0 ja 1 yhdistelmä:

$$ \mid\psi> = \frac{1}{\sqrt{2}}\mid0>+\frac{1}{\sqrt{2}}\mid1> $$

Alla olevassa koodiesimerkissä käytetään IBM:N qiskit python-kirjaston funktioita ja luodaan yhden kubitin kvanttipiiri. Kuvassa kubitin tila esitetään Blochin pallon pinnalla. Kun kubittiin operoidaan H-portilla, kubitti siirtyy tilojen 0 ja 1 yhdistelmätilaan. Jos superpositiotila mitataan, on yhtä suuri todennäköisyys mitata bitin arvoksi 0 tai 1. Huomaa, että tilavektorin kärki on yhtä kaukana pallon molemmista navoista.

Kubitin lopullinen tila määräytyy vasta kun kvanttitietokoneessa mitataan kubitin sisältämä informaatio ja tallennetaan se klassisen tietokoneen muistiin. Kun kubitin tila mitataan, niin kubitti tuhoutuu ja saatu mittaustulos tallennetaan klassisen tietokoneen rekisteriin bitin arvona 0 tai 1. Suorittamalla hyvin suuri määrä identtisiä mittauksia aivan samalla systeemillä, saadaan selville todennäköisimmät lopputilat, joihin kubitit asettautuvat kvanttiporttien vaikutuksesta. Yhtälön kertoimet a ja b liittyvät kummankin tilan esiintymistodennäköisyyksiin: luvun $a$ neliö $a^2$ on todennäköisyys, että mittaustulokseksi saadaan klassinen bitti 0. Vastaavasti luvun $b$ neliö $b^2$ ilmaisee todennäköisyyden saada mittaustulokseksi bitti 1.

Kuvassa on esitetty miten Qiskit-kirjaston funktoiden avulla on määritelty kolmesta kubitista muodostuva kvanttipiiri.

kuva1

Kun jokaiseen kubittiin q operoidaan Hadamard-portilla eli H-portilla, asettuvat kubitit toisistaan riippumatta tilojen 0 ja 1 superpositioon:

$$ \mid\psi> = \frac{1}{\sqrt{2}}\mid0>+\frac{1}{\sqrt{2}}\mid1> $$

Kun yksittäisen kubitin tila mitataan ja mittaustulos tallennetaan klassiseen rekisteriin (nuoli kuvassa), on molempien mahdollisten mittaustulosten 0 ja 1 todennäköisyys sama:

$$P\left(0\right)=P\left(1\right)=\left(\frac{1}{\sqrt{2}}\right)^2=0.5$$

.

Koska jokaisella kolmella kubitilla on kaksi mahdollista lopputilaa, niin kolmen bitin mittaustulos voi olla 2^3 = 8 erilaista bittien 0 ja 1 yhdistelmää:

Kaikilla bittien $0$ ja $1$ yhdistelmillä on sama todennäköisyys, koska kubitin tilan määräytyessä mittaustapahtumassa jokaisella mitatulla bitillä on 50% :n esiintymistodennäköisyys olla $0$ tai $1$. Kun haluamme esittää arvottavat lottonumerot väliltä $1-40$, niin tarvitsemme luvun $40=32 +8= 2^5+2^3$ esittämiseen vähintään 6 bittiä ($2^5$ ja lisäksi $2^0$).

Yllä olevassa kuvassa kubiteilla $0 -6$ on jokaisella 50%:n todennäköisyys asettua mittauksessa lopputilaan $0$ tai $1$. Kun kvanttialgoritmisuoritetaan saadaan tulokseksi satunnainen binääriluku, jossa on $7$ bittiä. Algoritmi simuloidaan tietokoneella hyvin montakertaa ja mittaustuloksina saadut erilaiset 7:n bitin yhdistelmät ja niiden esiintymisfrekvenssit tallennetaan python sanakirjaan. Lottonumeroksi valitaan se binääriluku, jolla on suurin esiintymisfrekvenssi. Jos numero on jo valittu tai numero suurempi kuin 40, niin arvonta suoritetaan uudelleen.