2.5.2 Vertailuoperaattorit

C++ tuntee seuraavat kuusi vertailuoperaattoria:

==

yhtä suuri kuin

!=

eri suuri kuin

<

pienempi kuin

<=

pienempi tai yhtä suuri kuin

>

suurempi kuin

>=

suurempi tai yhtä suuri kuin

Nämä operaattorit muodostavat totuusarvoisia lausekkeita, joita voidaan käyttää ehtolauseen ehtoina. Totuusarvoisella lausekkeella tarkoitetaan kahden alkion (luku, merkki,...) vertailua, josta palautetaan tieto vertailun paikkansa pitävyydestä: jos vertailu piti paikkansa, palautetaan tosi (true), ja jos vertailu ei pitänyt paikkaansa, palautetaan epätosi (false). Kuten edellisestä muistetaan, totuusarvot esitetään C++-kielessä kokonaislukujen avulla. Luku 0 vastaa arvoa epätosi ja muut luvut tarkoittavat arvoa tosi.

(5 == 5) palauttaa arvon tosi
(5 == 6) palauttaa arvon epätosi
(5 < 6) palauttaa arvon tosi

Jossakin ohjelmassa voisi olla vaikkapa seuraavanlainen pätkä:

if (kk < 5)
  cout << "Synttärit tulossa!" << endl;

if (kk == 5) {
  cout << "Näin se ikä karttuu..." << endl;
  ika_vuosissa++;
}

if (kk > 5)
  cout << "Synttärit meni jo!" << endl;

Yhtäsuuruusoperaattorin käyttö aiheuttaa suurimman osan ehtolauseissa esiintyvistä virheistä, joten on aiheellista antaa huomautus:

Yhtäsuuruutta testaava operaattori on ==, eikä suinkaan operaattori =, joka asettaa muuttujalle arvon.

Hyvin tavanomainen virhe on kirjoittaa ehtolauseeseen epähuomiossa sijoituslause yhtäsuuruusvertailun sijasta. C++-kieli ei periaatteessa ole tästä moksiskaan sillä esim. lauseessa

if (kk = 5) cout << "On toukokuu" << endl;   /* VÄÄRIN!! */

ei mitään varsinaista virhettä C++-kielen syntaksin mukaan tapahdu. Kuitenkin ohjelman käyttäjä voi suuresti ihmetellä, kun ohjelma itsepintaisesti väittää, että on toukokuu, annettiinpa kuukauden numeroksi mitä hyvänsä, esim. -1352.

Mistä siis kiikastaa? Katsotaanpa "ehtolauseketta". Sulkuihin kirjoitetussa lausekkeessa

kk = 5

ei suinkaan kysytä, onko muuttujan kk arvo 5, vaan siinä asetetaan muuttujan kk arvoksi 5. Arvon asetuksen jälkeen muuttujalle asetettu arvo palautetaan koko asetuslausekkeen arvoksi. Näin ollen ehtolausekkeen arvo tässä tapauksessa on 5, nollasta poikkeava kokonaisluku, joka tulkitaan arvoksi true, joten ehdon perässä oleva tulostuslause suoritetaan aina. Lisäksi ohjelma toimii luultavasti muutenkin omituisesti, sillä tämän "ehtolauseen" suorituksen jälkeen muuttujan kk arvo on aina 5 riippumatta siitä, miksi se aiemmin ohjelmassa on asetettu.

Kyseinen virhe on aikojen saatossa ollut niin yleinen hämmennysten aiheuttaja, että nykyiset kääntäjät yleensä antavat tällaisesta sijoituksesta varoituksen.

Ehtolauseke voi sisältää vertailuoperaation lisäksi aritmeettisia operaatioita. Voidaan kirjoittaa esim. seuraava ehtolause

if (lkm*kplhinta > rahaa_kaytettavissa)
  cout << "Hupsista! Rahat ei riitä." << endl;

Edellisessä ehtolausekkeessa ei tarvita sulkuja, sillä kaikki aritmeettiset operaatiot suoritetaan ennen vertailuoperaatioita.

Liukulukujen yhtäsuuruuden vertailu ei välttämättä tuota haluttua tulosta.

Kuten on nähty, liukulukuesitys tuottaa luvulle pakostakin hyvin likimääräisen esityksen. Näin ollen kahden liukuluvun yhtäsuuruuden suora testaaminen ei välttämättä tuota haluttua tulosta, sillä luvuissa voi esiintyä pieniä heittoja. Parempi tapa on verrata lukujen erotuksen itseisarvoa (tai vaikkapa sen neliötä) johonkin pieneen lukuun.

Erityisesti vertailu

luku == 0.0

saattaa epäonnistua näyttävästi. Aritmeettisten operaatioiden tuloksena harvoin, jos koskaan, saadaan "puhdasta" nollaa, sillä liukuluvut pyritään aina esittämään normeerattuina. Tällöin siis esitettävä luku on aina nollasta eroava (sillä mantissa 0.5), ja nolla esitetään hyvin pienen luvun itseisarvona.

Oikeampi tapa liukulukujen vertailuun on:

#include <math.h>
#define PIENI 0.0005
...
if (fabs(luku) < PIENI)
  cout << "Luku on liian lähellä nollaa!" << endl;
...
if (fabs(luku1-luku2) < PIENI)
  cout << "Luvut 1 ja 2 ovat liian lähellä toisiaan!" << endl;

Tässä fabs on kirjastossa math määritelty funktio, joka palauttaa liukuluvun itseisarvon. (Kokonaisluvun itseisarvon voi laskea funktiolla abs ja pitkän kokonaisluvun itseisarvon funktiolla labs; nämä on määritelty kirjastossa stdlib.)