1.8 0.1 # => 1.9
1.8 0.1 == 1.9 # => false
1.8 0.1 > 1.9 # => true
Miksi se on näin?
1.8 0.1 == 1.9 # => false
1.8 0.1 > 1.9 # => true
Miksi se on näin?
Turvaa tilisi vahvistamalla puhelinnumerosi. Voit silloin palauttaa unohtuneen salasanan tekstiviestillä.
Näihin keskusteluihin ei ole vielä vastattu. Ole ensimmäinen.
Vastaukset 7
Vanhimmat
Tässä on nyt kysymys siitä, että tietokoneiden käyttämä liukulukuesitys ei kykene esittämään kaikkia lukuja tarkasti.
Tämä on monelle aloittelevalle ohjelmoijalle kova pala!
http://fi.wikipedia.org/wiki/Liukuluku
Jos osaat englantia:
http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
Ja kuivaks. Ehkä tämä selittää paremmin...
Tietokone ei siis pysty esittämään desimaalilukua 1.8 tarkasti (eksaktisti) liukulukuna vaan siitä tulee esim. 1.8000001. Ja jos sitten 1.9 samasta syystä on esim. 1.8999999, niin sotkua tulee:
1.8 0.1 onkin siis 1.8000001 0.1000000 ja tulokseksi tulee esim. 1.9000001
1.9000001 ei ole 1.8999999
1.9000001 on suurempi kuin 1.899999
Vedin luvut hatusta eli ne ei välttämättä ole juuri nuo mitä esitin. Mutta periaate on kuitenkin tämä!
otetaan pieni heitto huomioon:
eli inteis vertailu jos samat (eli TRUE)
if( iLuku1==iLuku2 ) blah;
ja flotareis
const float EPSILON 0.0001f; // tai jotain
if ( fabs(fLuku1 - fLuku2) < EPSILON ) blah;
"Tietokone ei siis pysty esittämään desimaalilukua 1.8 tarkasti (eksaktisti) liukulukuna vaan siitä tulee esim. 1.8000001. "
Ymmärrän sen kun tietokone käyttää bittejä (32 tai 64) niin lukuja joudutaan pyöristelemään jolloin virheitä tulee. Mutta miksi noin jos luku on vain 1.8?
Vai pitääkös tietokoneen täyttää nuo loppubitit jolloin joudutaan tekemään 1.8....1 koska desimaali luvuissa ei vika voi olla 0?
http://en.wikipedia.org/wiki/Floating_point
:: The problem is that floating-point numbers with
:: a limited number of digits can represent only a
:: subset of the real numbers, so any real number
:: outside of that subset (e.g. 1/3, or an
:: irrational number such as π), cannot be
:: represented exactly. Even numbers with
:: extremely short decimal representations can
:: suffer from this problem. The decimal number
:: 0.1 is not representable in binary
:: floating-point of any finite precision. The
:: exact binary representation would have a "1100"
:: sequence continuing endlessly:
::
::
:: e=-4; s=1100110011001100110011001100110011...,
:: but when rounded to 24 bits it becomes
::
:: e=-4; s=110011001100110011001101 which is
:: actually 0.100000001490116119384765625 in
:: decimal.
Liukuluvut esitetään jokseenkin näin (binäärinä):
m * 2^e
m = mantissa
e = eksponentti
Edes lyhyttä desimaalilukua 0.1 on siis mahdoton esittää tarkasti, koska se vaatii loputtomasti toistuvan bittijakson 1100.
Luvun 0.1 tarkka esitys:
m = 1100 1100 1100 1100 1100 1100 (loputtomiin asti)
e = -4
Luvun 0.1 esitys 24 bitillä:
m = 1100 1100 1100 1100 1100 1101
e = -4
mikä on desimaalilukuna noin 0.100000001490116119384765625.
Summa summarum:
Ongelma on se, että kun tietokoneessa reaaliluvut esitetään binäärisinä liukulukuina, niiden tarkkaa esittämistä varten tarvitaan usein loputon määrä bittejä. Mutta koska bittejä ei ole loputtomia määriä vaan niitä on esim. 53 bittiä mantissaa varten, silloin joudutaan tarkka esitys katkaisemaan ja syntyy virhettä.
Koko ketjusta minulle tuli mieleen:
miksei voisi tehdä systeemiä, jossa laskettaisiin reaaliluvuilla. Hitaampihan se tietysti on, mutta koneet ovat nykyään nopeita.
Reaaliluvut eivät ole edes teoriassa minkään äärellisen koneen käsiteltävissä ja koneen on oltava äärellinen, että sitä voisi ajaa. Pidempi selitys menisi erittäin tekniseksi...
Usein ohjelmoinnin kursseilla puhutaan reaaliluvuista kun tarkoitetaan liukulukuja.