A floating point problémát mi okozza, hogy idézhető elő és mit lehet tenni ellene?
Látom, az egyik megoldást meg is találtad.
De van még:
* Racionális számokat használsz.
* Sokkal pontosabban számolsz, mint ahogy kellene, és kerekítesz.
* Szimbolikusan számolsz.
# 5/11 Időpont tegnap 23:28
# 6/11 Időpont tegnap 23:31
Nem érted a problémát. A gép kettesben számol, kettőhatványokkal. Kettő hatványaival (többet között) az 1/10-et nem tudod felírni pontosan.
De vegyünk egy egyszerűbb, tizes számrendszerbeli példát, az 1/3-ot:
3/10 + 3/100 + 3/1000 ... stb.-vel tudod közelíteni. De pontosan felírni nem. Nézzük meg mi történik ha csak tizedekkel írnád fel:
1/3+1/3+1/3 = 1
3/10 + 3/10 + 3/10 = 9/10
Ez elég messze van a kívánt eredménytől.
Százasokkal:
1/3+1/3+1/3 = 1
(3/10 + 3/100) + (3/10 + 3/100) + (3/10 + 3/100) = 99/100
Ez már közelebb van, de még mindig messze.
És így tovább, ezt a végtelenségig lehet játszani, de sosem fogsz 1-et kapni eredményként korrekció nélkül, csak egy nagyon-nagyon közeli számot.
Kérdező, amit te itt felvázolgatsz, az egy egészen eltérő számábrázolás. A számítógép ugye binárisan számol, egyesek és nullák sorozatával. A floating point (avagy lebegőpontos) számábrázolásban a teljes szám egy bináris hatványsor, tehát minden 'számjegy' a kettő valamely hatványának felel meg.
Pl a 12,25 az a következőnek felelne meg:
1100,01
Miért? Nézzük külön az egész, ésa tört részét.
1100 az 0*1 + 0*2 + 1*4 + 1*8 azaz 12. míg a törtrészben levő szám 0*(1/2) + 1*(1/4), azaz 0,25. Így pontosan kijön a 12,25.
De ha mondjuk a 0,3-at akarnánk ábrázolni, bajban lennénk. Az valahogy így kezdene el kinézni:
0,0100110011001100... és így tovább. A szám amit most felírtam tizedes számrendszerbe visszafejtve 0.29998779296875-nek felel meg. Nem 0,3, de közel van hozzá. Minél tovább számoljuk ki, annál közelebb lesz, de soha nem lesz pontosan 0.3. Ebből fakad a lebegőpontos számok kerekítési problémája.
Ugyanakkor van olyan számábrázolás, ahol az egész részt és a tört részt is külön-külön decimális számmal jelöljük. Ennek előnye, hogy x számjegyig valóban pontos számolást tudunk mutatni, hátránya, hogy a legkevésbé sem hatékony vele dolgozni.
Nem értem :(
Legyen szó bármilyen számról azt lehet konvertálni pontosan binárisba és vissza is decibe. Ezért ha a gép binárisba számol akkor két bináris összeget összeadva megkapjuk az eredményt ami decibe is visszakonvertáva megfelelő. És most valós számokról beszélek.
IEEE-754 azt hiszem ez szerint működik az hogy a gép miképpen ábrázol, vagy számol valós számokkal. De akkor nem a binaritásban kereső az a hiba hogy nem képes pontosan számolni a gép bizonyos esetekben hanem a szabványé mert ez határozza meg azt hogy a gép milyen esetben milyen számítási műveletet végezzen a binárisokon.
Gondolom az aposztrófnak is megvan a binárisa mint minden másnak jelezzük ez most A nak és akkor a fenti példa így nézne ki :
00000000A00000011 + 00000000A00000011 = 00000000A00000110
Miért ne lehetne ilyen egyszerűen, volna egy típus ami tisztába van azzal mi az aposztróf binárisa és két részre lehetne osztani a számítást egészekre és törtekre.
A pontosság pedig már csak memóriától függne. És nincsenek hibák sem. És a gép is pillanatok alatt összedobja azt a két részt. Miért nem így van a másik számításigényesebb hibákat okozó helyett.
A példa amit kihagytam :
0.3+0.3= 0.6
Nagyon egyszerű ilyenkor a dolog: ne floatot használj, hanem a hagyományos integert! Az integer angolul ponthogy az egész számot jelenti, amit te valamiért NAGYON helytelenül valós számoknak hívsz konzekvensen. ( [link] )
Egyszerűen nem használsz tizedesvesszőt sehol, hanem így a szám 100-, 10000-, vagy 100000-szeresével dolgozol. Egyedül amikor kiírod a usernek a képernyőre, akkor bedobsz egy tizedesvesszőt a megjelenítésben a 3., 5., vagy a 6. számjegy elé. problem solved.
Természetesen ugyanez visszafele, hogy ha a user törtet ír be egy inputmezőbe, akkor azt azon nyomban integerré alakítod. És mivel a programon belül te mindig integerrel (vagy akár longinttel) számolsz, így sosem lesz kerekítési hibád.
A float, azaz a lebegőpontos számábrázolás tipikusan arra való, ha borzasztóan nagy (vagy kicsi) számokkal kell dolgoznod, amik a longintbe se férnének bele. De ha ilyen piszlicsáré milliárd alatti számaid vannak, akkor totál felesleges a float-ot erőltetned.
Ahhoz, hogy megertsd az elonyoket es a hatranyokat, ahhoz elobb meg kene ertened hogyan mukodnek a dolgok.
De ha a 2 a 100-dikon szamot akarjuk abrazolni az altalad vazolt modszerrel, akkor 99 nullat tarolunk kb tok feleslegesen. Floatnal erre nincs szukseg, eltarolsz egy 1-est meg egy binaris 100ast es kesz. Most arra nem ternek ki h sokszor szamolni is egyszerubb vele.
Kapcsolódó kérdések:
Minden jog fenntartva © 2025, www.gyakorikerdesek.hu
GYIK | Szabályzat | Jogi nyilatkozat | Adatvédelem | Cookie beállítások | WebMinute Kft. | Facebook | Kapcsolat: info(kukac)gyakorikerdesek.hu
Ha kifogással szeretne élni valamely tartalommal kapcsolatban, kérjük jelezze e-mailes elérhetőségünkön!