Forum » Programiranje » float vs decimal
float vs decimal
kuall ::
Kle je ena zbrka spet. Mau no. Saj se mi zdi, da mi je jasno. Samo ko tole iščeš po internetu težko najdež jasen odgovor, en kup enega nakladanja!
Problem je kako se izognit napakam pri zaokroževanju v Sql, C# etc kodi, ko uporabljaš decimalne številke.
Ko bereš članke po internetu bodo nakladali, da je float približna vrednost, decimal pa točna. Kar je en bullshit. Oboji sta približna vrednost, samo da je decimal bolj točna, ker zaseda več mest v spominu in lahko shrani več decimalnih mest. Float pa je hitrejši, ker lahko uporablja cpu hawrdware za računanje, medtem ko decimal uporablja software za računane.
tak da float bo shranil 1/3 takole:
0.333333
decimal (38,18) pa takole
0.3333333333333333333333333333333333333 (no v resnici dobiš tole: 0.333333000000000000, tu je še en čuden trik)
V C# ima double 2x tolikšno natančnost kot float (ker ima 8 bajtov namesto 4), decimal pa 3x tolikšno kot float, ker ima 12 bajtov. V SQL ima float 8 bajtov, decimal (38, 18) pa ima 17 bajtov.
Moja razlaga :
Ko shraniš vrednost je vseeno v kaj jo shraniš, lahko je komot float ali money. Tak da ali definiraš neko sql kolono kot float ali money ali decimal je čist vseeno, tu ne bo natančnost trpela. ker itak vedno shraniš ponavad končno izračunano vrednost, ki je ponavadi samo na 2 ali 4 cente (decimalna mesta) natančna, več ne rabijo ljudje kot to. saj zato pa ima money samo 4 decimalna mesta. ima pa velik razpon vrednosti, ker znajo bit denarne vsote zelo velike, npr. ameriški dolg ne moreš shranit sem not spljoh.
Ko pa delaš kalkulacije pa moraš money ali float pretvorit v decimal (38, 18), če hočeš maximalno natančnost. Pač je nerodno, če za kakšen cent narobe izračunaš, čeprav zarad tega ne bo konc sveta ampak vseeno, ljudje so občutljivi na te cente.
Do napak pri računanju z zaokrožćenimi vmesnimi vrednostmi pa prihaja zato, ker se tisti izbrisane decimalke lahko v nadaljnih korakih naberejo skupaj, da prerastejo v eno višjo decimalko, ki jo kažemo.
npr:
1.23456789 * 100000 = 1234567.89
1.234567 * 100000 = 1234567.00
Ravnokar si izgubil skoraj 1 EUR.
torej če bi imel definirano ceno na vrečo, za vrečo pa določeno težo in bi hotel izračunat ceno za 100.000lkg bi moral vmesno vrednost - ceno na kg - shranit v decimal (38,18), da ne bi na koncu izgubil centov. oziroma če bi izračun naredil v enem koraku moraš tudi pretvorit vsako vrednost v decimal (38,18), ker drgač je sql servermau neumen in npr 1/3 vrne kot 0, 1/3.0 pa vrne kot 0.333333. Zgleda, da ima končni rezultat decimalke po eni od vrednoti, samo po tisti v imenovalcu al kva? spet en neumen trik.
Tole je čist logična razlaga ampak je zaboga ne boš našel nikjer na internetu.
Problem je kako se izognit napakam pri zaokroževanju v Sql, C# etc kodi, ko uporabljaš decimalne številke.
Ko bereš članke po internetu bodo nakladali, da je float približna vrednost, decimal pa točna. Kar je en bullshit. Oboji sta približna vrednost, samo da je decimal bolj točna, ker zaseda več mest v spominu in lahko shrani več decimalnih mest. Float pa je hitrejši, ker lahko uporablja cpu hawrdware za računanje, medtem ko decimal uporablja software za računane.
tak da float bo shranil 1/3 takole:
0.333333
decimal (38,18) pa takole
0.3333333333333333333333333333333333333 (no v resnici dobiš tole: 0.333333000000000000, tu je še en čuden trik)
V C# ima double 2x tolikšno natančnost kot float (ker ima 8 bajtov namesto 4), decimal pa 3x tolikšno kot float, ker ima 12 bajtov. V SQL ima float 8 bajtov, decimal (38, 18) pa ima 17 bajtov.
Moja razlaga :
Ko shraniš vrednost je vseeno v kaj jo shraniš, lahko je komot float ali money. Tak da ali definiraš neko sql kolono kot float ali money ali decimal je čist vseeno, tu ne bo natančnost trpela. ker itak vedno shraniš ponavad končno izračunano vrednost, ki je ponavadi samo na 2 ali 4 cente (decimalna mesta) natančna, več ne rabijo ljudje kot to. saj zato pa ima money samo 4 decimalna mesta. ima pa velik razpon vrednosti, ker znajo bit denarne vsote zelo velike, npr. ameriški dolg ne moreš shranit sem not spljoh.
Ko pa delaš kalkulacije pa moraš money ali float pretvorit v decimal (38, 18), če hočeš maximalno natančnost. Pač je nerodno, če za kakšen cent narobe izračunaš, čeprav zarad tega ne bo konc sveta ampak vseeno, ljudje so občutljivi na te cente.
Do napak pri računanju z zaokrožćenimi vmesnimi vrednostmi pa prihaja zato, ker se tisti izbrisane decimalke lahko v nadaljnih korakih naberejo skupaj, da prerastejo v eno višjo decimalko, ki jo kažemo.
npr:
1.23456789 * 100000 = 1234567.89
1.234567 * 100000 = 1234567.00
Ravnokar si izgubil skoraj 1 EUR.
torej če bi imel definirano ceno na vrečo, za vrečo pa določeno težo in bi hotel izračunat ceno za 100.000lkg bi moral vmesno vrednost - ceno na kg - shranit v decimal (38,18), da ne bi na koncu izgubil centov. oziroma če bi izračun naredil v enem koraku moraš tudi pretvorit vsako vrednost v decimal (38,18), ker drgač je sql servermau neumen in npr 1/3 vrne kot 0, 1/3.0 pa vrne kot 0.333333. Zgleda, da ima končni rezultat decimalke po eni od vrednoti, samo po tisti v imenovalcu al kva? spet en neumen trik.
Tole je čist logična razlaga ampak je zaboga ne boš našel nikjer na internetu.
- spremenilo: kuall ()
smacker ::
Kakšno napako povzročiš pri izračunih lahko izračunaš s pomočjo relativne absolutne napake (če zaokrožiš na celo število, je absolutna napaka +- 0,5). V računalništvu se izračun malo zakomplicira, ker navadno "zaokrožuješ" binarna števila. Računa se tudi relativna napaka(absolutna/izračunana vrednost) - če iz 99,9 zaokrožiš na 100 to ni tako hudo, kot če 0,1 zaokrožiš na 0. Maš tud pravila, kaj se dogaja z absolutno/relativno napako pri izvajanju računskih operacij. S pomočjo tega se določi tudi "računska stabilnost" postopka. Pogosto lahko z zamenjavo vrstnega reda operacij močno povečaš stabilnost nekega sistema (recimo se izogneš deljenju z zelo majhnimi števili, blizu nič). S tem se ukvarja numerična matematika, če te zanima teorija.
Za praktično rabo pa najdeš pojasnila v dokumentaciji posameznih programskih jezikov. Float/double so navadno predstavljenmi kot kombinacija mantise in eksponenta, zato je število decimalnih mest ki jih lahko shraniš obratno sorazmerno z velikostjo števila (temelji na predpostavki da pri miljardi decimalke niso tako pomembne). Razni decimal in podobni tipi pa so navadno predstavljeni kar kot niz znakov in imajo definirane posebne operatorje - postopek izračuna je podoben kot če pisno množiš/deliš/seštevaš/odštevaš na papir.
Tako so pač definirani operatorji. Glede na operator in podatkovni tip operandov se izvede ustrezna programska koda. INT/INT v večini (vseh?) programskih jezikih vrača INT. Zakaj? Ker so celoštevilske operacije hitrejše. Če želiš "točnejši" rezultat moraš števec ali imenovalec pretvorit v DOUBLE: 1/3.0, 1/(3*1.0), 1/(double)3,...). Pri DOUBLE/INT ali INT/DOUBLE pa se vrača DOUBLE (ali float, decimal,...).
Za praktično rabo pa najdeš pojasnila v dokumentaciji posameznih programskih jezikov. Float/double so navadno predstavljenmi kot kombinacija mantise in eksponenta, zato je število decimalnih mest ki jih lahko shraniš obratno sorazmerno z velikostjo števila (temelji na predpostavki da pri miljardi decimalke niso tako pomembne). Razni decimal in podobni tipi pa so navadno predstavljeni kar kot niz znakov in imajo definirane posebne operatorje - postopek izračuna je podoben kot če pisno množiš/deliš/seštevaš/odštevaš na papir.
ker drgač je sql servermau neumen in npr 1/3 vrne kot 0, 1/3.0 pa vrne kot 0.333333. Zgleda, da ima končni rezultat decimalke po eni od vrednoti, samo po tisti v imenovalcu al kva? spet en neumen trik.
Tako so pač definirani operatorji. Glede na operator in podatkovni tip operandov se izvede ustrezna programska koda. INT/INT v večini (vseh?) programskih jezikih vrača INT. Zakaj? Ker so celoštevilske operacije hitrejše. Če želiš "točnejši" rezultat moraš števec ali imenovalec pretvorit v DOUBLE: 1/3.0, 1/(3*1.0), 1/(double)3,...). Pri DOUBLE/INT ali INT/DOUBLE pa se vrača DOUBLE (ali float, decimal,...).
jype ::
je izjavil:
Ko pa delaš kalkulacije pa moraš money ali float pretvorit v decimalČe si denar kadarkoli zapisal kot float, si že naredil napako.
kuall ::
V bistvu float (in double) ne prideta v poštev nikjer kjer rabiš točne vrednosti. vse kar izdeluje/šteje človek: denar, dimenzije. oziroma lahko bi rekli vse "diskretne" vrednosti? vse kar se da prešteti, kot so centi pri denarju.
float pa bi v kakšni igrci, animaciji itd uporabil, kjer je vseeno ali je 1 pixel malo bolj v desno ali levo. pa kjer rabiš hitrost.
jype, spet smetiš s svojimi napol odgovori.
je še ena razlika med float in decimal. decimal se zapiše dobesedno: vsak digit se zapiše v spomin tak kot je, brez pretvarjanja. si lahko 100%, da ko ga boš prebral bo tak prišel tudi nazaj, kot si ga zapisal.
medtem ko pri float poteka pretvarjanje v binarno obliko, da se biti nekak čudno seštevajo in množijo, da na koncu dobiš končno številko, in med to pretvorbo že lahko pride teoretično do napake, da ko boš zapisal npr. 30000.14 kot float bo to pretvoril v 30000.1 v mysql. ampak v ms sql tega ni.
float pa bi v kakšni igrci, animaciji itd uporabil, kjer je vseeno ali je 1 pixel malo bolj v desno ali levo. pa kjer rabiš hitrost.
jype, spet smetiš s svojimi napol odgovori.
je še ena razlika med float in decimal. decimal se zapiše dobesedno: vsak digit se zapiše v spomin tak kot je, brez pretvarjanja. si lahko 100%, da ko ga boš prebral bo tak prišel tudi nazaj, kot si ga zapisal.
medtem ko pri float poteka pretvarjanje v binarno obliko, da se biti nekak čudno seštevajo in množijo, da na koncu dobiš končno številko, in med to pretvorbo že lahko pride teoretično do napake, da ko boš zapisal npr. 30000.14 kot float bo to pretvoril v 30000.1 v mysql. ampak v ms sql tega ni.
kuall ::
Torej uporabiš DECIMAL(19, 6) ali DECIMAL (20,2) ali MONEY za shranit denar na disk, če pa moraš delat preračunavanja pa vse vmesne vrednosti najprej pretvoriš v DECIMAL (38, 18), končni rezultat pa spet nazaj v DECIMAL (19, 6)
Zgodovina sprememb…
- spremenilo: kuall ()
jype ::
jype, spet smetiš s svojimi napol odgovori.Ne. "Pretvarjanje iz float" je že samo po sebi narobe. Ko operiraš z denarnimi enotami, moraš uporabljati podatkovni tip decimal.
medtem ko pri float poteka pretvarjanje v binarno obliko, da se biti nekak čudno seštevajo in množijoJežeštana. Temu se reče IEEE 754 matematika: IEEE 754 @ Wikipedia
pegasus ::
kako se izognit napakam pri zaokroževanjuTo je fundamentalno vprašanje v računalništvu. Odgovor je nepriejten - ne moreš se. IEEE754 ti tega enostavno ne omogoča.
Dobra novica je, da je rešitev že na vidiku - unum oz. sedaj že v tretji iteraciji, posit. Implementacije, s katerimi se lahko igraš, najdeš vsaj za okolji Mathematica in Julia, zelo verjetn še za kako. Čakamo, da se pojavi hardver, ki te oblike zapisa števil podpira, potem bo šele veselje :)
kuall ::
jype, kaj pa če bi se ti izogibal pogovarjanju z menoj? bom zelo vesel, če se mi ne bo nikoli več treba pogovarjat s teboj. ti tvoji napol odgovori in limanje linkov mi gredo res na živce. vem kako se temu reče, sem ravnokar bral, pač opisal sem to potem s svojimi besedami. res pa da se prej nisem nikoli v to prav zelo poglabljal.
ja človek pričakuje, da je float že zdaj "unum", pa žal ni. pač to je ta problem, ko pričakuješ, da stvari delujejo "pravilno", ko v resnici ne in moraš sam poskrbet za njih. tudi tale decimal (x,y) je precej debilen. saj ne moreš točno vedet, koliko bo max številka. pa to da moraš za vmesno računanje pretvarjat v decimal (38,18) je tudi debilno, to bi lahko jezik sam vedel, da mora.
sta pa c# decimal in sql decimal (38,18) ista stvar, ne?
ja človek pričakuje, da je float že zdaj "unum", pa žal ni. pač to je ta problem, ko pričakuješ, da stvari delujejo "pravilno", ko v resnici ne in moraš sam poskrbet za njih. tudi tale decimal (x,y) je precej debilen. saj ne moreš točno vedet, koliko bo max številka. pa to da moraš za vmesno računanje pretvarjat v decimal (38,18) je tudi debilno, to bi lahko jezik sam vedel, da mora.
sta pa c# decimal in sql decimal (38,18) ista stvar, ne?
moose_man ::
ja človek pričakuje, da je float že zdaj "unum", pa žal ni. pač to je ta problem, ko pričakuješ, da stvari delujejo "pravilno", ko v resnici ne in moraš sam poskrbet za njih.
Ja tega ne smeš pričakovat. :)
Res pa je, da se je najbrž treba enkrat ali dvakrat opečt pri uporabi floating pointa, da ti zavedanje o njegovih nevarnostih dovolj zleze pod kožo. :) To pa itak velja na splošno tudi za druge stvari ...
Podobno kot si izbiraš, s kakšnim algoritmom boš nekaj rešil, si lahko tudi izbereš kakšen precision boš uporabil. S tem da potem ko imaš nekaj izkušenj o tem sploh več aktivno ne razmišljaš.
noraguta ::
standard je definiran z napakami vred. sicer pa ponucaš kako arbitrary precision knjižnico ampak to ni sql pa ta drek. tudi haskel in kaka implementacija lispa se znata pogovarjat s števili poljubne natančnosti. odvisn kva nucaš.
Pust' ot pobyedy k pobyedye vyedyot!
smacker ::
to bi lahko jezik sam vedel, da mora.
Ne, ne rabi. Če delam z INT, hočem da je program hiter, ne pa da mi pametuje z pretvorbami v double. Če potrebujem večjo natančnost, bom mu že sam povedal naj uporabi double. Če hočeš max. natančnost, potem daj vse tipe v bazi na decimal (38,18). Če delaš račune, ki potrebujejo večjo natančnost od 38 cifer, potem poiščeš primerna matematična orodja (matlab,...).
Spura ::
V prvem postu je tok enih stvari narobe da je kr grozno. Neko izenacevanje sql tipov in C# tipov, decimal je 16 bajtov in ne 12, in podobne fore. Ne locuje tip sploh kaj je v SQLu in kaj je v C#.
kuall ::
Najprej praviš, da je polno stvari narobe, potem pa ne moreš citirati ene, no ena je res narobe, 16 bajtov namesto 12 ja, hitro sem tipkal.
C# in Sql tipe moraš primerjat (ne izenačujem jih), ker se ta dva jezika uporabljata skupaj in moraš vedet, kaj paše skupaj.
Jype št. 2. Pa še kakšen se bo našel. Se čudim, da jih ni bilo več. :D
C# in Sql tipe moraš primerjat (ne izenačujem jih), ker se ta dva jezika uporabljata skupaj in moraš vedet, kaj paše skupaj.
Jype št. 2. Pa še kakšen se bo našel. Se čudim, da jih ni bilo več. :D
Zgodovina sprememb…
- spremenilo: kuall ()
kod ::
Enostavno povedano ti decimal zagotavlja točnost v desetiškem sistemu, float pa ne(pri float je zagotovljena točnost v dvojiškem sistemu).
Naprimer števila 0.1 ni mogoče točno zapisati z float. Primer matematične operacije ki pokaže da float ni točen v desetiškem sistmu je to: 0.1*0.1 != 0.01
Naprimer števila 0.1 ni mogoče točno zapisati z float. Primer matematične operacije ki pokaže da float ni točen v desetiškem sistmu je to: 0.1*0.1 != 0.01
jype ::
kod ::
To z točnostjo v dvojiškem sistemu je mišljeno da pri float številu npr. 1001.1011(to je dvojiški zapis) je to točno tako kot je zapisano in ni približek ki nam bo pokvaril matematično operacijo kot se to zgodi ko float uporabimo za računanje desetiških števil (primer v moji prejšnji objavi)
kuall ::
Dober primer za testirat:
https://www.h-schmidt.net/FloatConverte...
Float je res nenatančen.
Čim večja je številka tem večje so napake pri decimalkah.
Večino številk se sploh ne da natančno zapisat v float.
Npr 3000000.14 se shrani kot 3000000.25
3.14 kot 3.1400001049041748046875
3.15 kot 3.150000095367431640625
V resnici so redke številke, ki se dajo shraniti točno, vse so samo približek.
Še nekaj testov:
Shrani se pa takole:
float ima 32 bitov.
prvi bit je sign
potem so biti za exponent
potem so biti za celo število (enostavno pretvoriš številko iz decimalnega številskega sistema v binarnega, to je enostavno)
potem pa so biti za decimalke, ki pa se pretvarjajo v binarni sistem na približen način (tu nastopijo napake). ta način je pa takle:
če je bit 0 potem ga ignoriramo.
če je bit 1 pa dodamo tole h končni številki: 1/(2*2*2*...) število dvojk določa pozicija bita.
integer del se da točno shranit zato, ker tam poteka množenje, ki vedno da točno celo številko (2*2*2)
decimalni del pa ne zato, ker tam poteka deljenje, ki da neko približno številko (1/(2*2*2))
To sploh ni tako enostavno za razumet, kot razni jypetki govorijo.
Tule je dobra razlaga:
https://en.wikibooks.org/wiki/A-level_C...
https://www.h-schmidt.net/FloatConverte...
Float je res nenatančen.
Čim večja je številka tem večje so napake pri decimalkah.
Večino številk se sploh ne da natančno zapisat v float.
Npr 3000000.14 se shrani kot 3000000.25
3.14 kot 3.1400001049041748046875
3.15 kot 3.150000095367431640625
V resnici so redke številke, ki se dajo shraniti točno, vse so samo približek.
Še nekaj testov:
declare @f float = 3000000.14 print @f -- 3000000, WRONG declare @d decimal (19,6) = 3000000.14 print @d -- 3000000.140000, CORRECT declare @f2 float = 0.1*0.1 print @f2 -- 0.01, CORRECT if @f2 = 0.01 print 'je' -- tole izpiše, CORRECT else print 'ni'
Shrani se pa takole:
float ima 32 bitov.
prvi bit je sign
potem so biti za exponent
potem so biti za celo število (enostavno pretvoriš številko iz decimalnega številskega sistema v binarnega, to je enostavno)
potem pa so biti za decimalke, ki pa se pretvarjajo v binarni sistem na približen način (tu nastopijo napake). ta način je pa takle:
če je bit 0 potem ga ignoriramo.
če je bit 1 pa dodamo tole h končni številki: 1/(2*2*2*...) število dvojk določa pozicija bita.
integer del se da točno shranit zato, ker tam poteka množenje, ki vedno da točno celo številko (2*2*2)
decimalni del pa ne zato, ker tam poteka deljenje, ki da neko približno številko (1/(2*2*2))
To sploh ni tako enostavno za razumet, kot razni jypetki govorijo.
Tule je dobra razlaga:
https://en.wikibooks.org/wiki/A-level_C...
smacker ::
V praksi maš fixed point arithmetic, zato ni "dela za celo število", samo mantisa in eksponent: Single-precision floating-point format @ Wikipedia
moose_man ::
Fixed point in floating point sta dve popolnoma različni reprezentaciji.
V fixed point reprezentaciji del bitov predstavlja celoštevilski del, preostanek bitov pa decimalke (en bit pa je rezerviran za predznak).
V floating point reprezentaciji del bitov predstavlja število iz polodprtega intervala [1, 2), drug del pa potenco števila 2. En bit je prav tako namenjen predznaku.
Če koga matra razumevanje floating pointa priporočam tole v branje (najbolj koristi pa seveda lastno eksperimentiranje):
http://fabiensanglard.net/floating_poin...
V fixed point reprezentaciji del bitov predstavlja celoštevilski del, preostanek bitov pa decimalke (en bit pa je rezerviran za predznak).
V floating point reprezentaciji del bitov predstavlja število iz polodprtega intervala [1, 2), drug del pa potenco števila 2. En bit je prav tako namenjen predznaku.
Če koga matra razumevanje floating pointa priporočam tole v branje (najbolj koristi pa seveda lastno eksperimentiranje):
http://fabiensanglard.net/floating_poin...
MH0 ::
je izjavil:
Ko pa delaš kalkulacije pa moraš money ali float pretvorit v decimalČe si denar kadarkoli zapisal kot float, si že naredil napako.
K temu ni veliko za dodati. Razen morda namigniti, da se zneske da zapisati tudi, kot integer v centih ali delčkih centov. #javascript #bitcoin
kuall ::
ni veliko za dodati? wtf je narobe z vami? mogoče razlago zakaj? no saj sem jo že sam dobil, vi mi je sigurno niste dali.
jype ::
Samo kazanje sebe kot zelo sposobnega ti gre.No prav, naj ti bo:
http://www.oxfordmathcenter.com/drupal7... razloži IEEE 754 tako, da bo tudi tebi jasno, čemu je zapis tak.
Jaz pa ti lahko razložim, čemu se denarja nikoli ne zapisuje na tak način: Osnovni problem je, da preslikava med zapisom IEEE 754 in decimalnim zapisom ni bijektivna. Obstajajo decimalna števila, ki jih _ne moreš_ natančno zapisati v IEEE 754. Napake se pri računanju seštevajo, zato absolutna napaka narašča, kar prej ali slej privede do centov in evrov, zaradi katerih te lahko računovodja ubije (običajno s pogledom, včasih pa kar s sovraštvom na daljavo), hkrati pa je takšno delo s številkami tudi prepovedano z računovodskimi standardi (ki ti jih ni _treba_ upoštevati, je pa pametno, da jih). Delo z decimalnim zapisom je znatno počasnejše (a z uporabo nekaterih trikov znosno), a poljubno natančno. V jezikih, kjer decimalne aritmetike ne poznamo, uporabljamo že omenjena cela števila, kjer decimalno vejico premaknemo za poljubno število mest v desno (in reč zgolj prikazujemo kot decimalno število, računamo pa s celimi).
Če potrebuješ žlico medu, da tvoje življenje ne bo tako grenko, si ga le privošči, če te še kaj zanima pa kar vprašaj.
Zgodovina sprememb…
- odbrisal: Mavrik ()
moose_man ::
Delo z decimalnim zapisom je znatno počasnejše (a z uporabo nekaterih trikov znosno)
Iz firbca, za kakšne trike gre tu? Če lahko na kratko orišeš (ni treba ful podrobno) ali daš kak link ... hvala.
Zgodovina sprememb…
- odbrisal: Mavrik ()
kuall ::
V bistvu se gre za to, da IEEE 754 zapiše decimalni del na takle način:
1/2^0 + 1/2^1 + 1/2^2 + 1/2^3 ....
S tem, da biti določajo, katere od teh se izpusti.
Potem ti je lahko jasno, zakaj je nemogoče zapisat večino decimalnih števil s float podatkovnim tipom.
Jype, razlaga se vedno s primeri. Trollanje ti gre bolje kot razlaganje, vaja dela mojstra.
1/2^0 + 1/2^1 + 1/2^2 + 1/2^3 ....
S tem, da biti določajo, katere od teh se izpusti.
Potem ti je lahko jasno, zakaj je nemogoče zapisat večino decimalnih števil s float podatkovnim tipom.
Jype, razlaga se vedno s primeri. Trollanje ti gre bolje kot razlaganje, vaja dela mojstra.
Zgodovina sprememb…
- spremenilo: kuall ()
jype ::
Iz firbca, za kakšne trike gre tu? Če lahko na kratko orišeš (ni treba ful podrobno) ali daš kak link ... hvala.Za uvod v decimalno aritmetiko priporočam Python dokumentacijo za modul decimal: https://docs.python.org/3/library/decim... . Zanimiv je tudi originalni PEP dokument, na katerega podlagi je nastala implementacija: https://www.python.org/dev/peps/pep-032... . V tipičnem jeziku bo za večino reči poskrbel že prevajalnik.
Na spletni strani standarda, na katerega se opira tudi python implementacija, so podatki o zmogljivosti: http://speleotrove.com/decimal/decperf....
Triki pa izhajajo iz Arbitrary-precision arithmetic @ Wikipedia oziroma aritmetike s poljubno natančnostjo, predvsem skozi uporabo t.i. "carry flag" (Carry flag @ Wikipedia ), ki omogoča malce manj neučinkovito računanje s števili, ki presegajo velikost registrov. Razlika je kljub temu potencialno ogromna (čeprav v povprečnem primeru niti ne tako drastična): O(N) proti O(1).
Jype, razlaga se vedno s primeri.Ja, saj zato sem prilepil povezavo na dokument, kjer so biti različne vrste v zapisu pobarvani, da je jasno, kateri kaj predstavlja (in je zraven zapisano tudi, čemu je tak zapis učinkovit):
Zgodovina sprememb…
- odbrisal: Mavrik ()
YaN-cH ::
je izjavil:
Ko pa delaš kalkulacije pa moraš money ali float pretvorit v decimalČe si denar kadarkoli zapisal kot float, si že naredil napako.
Spet obujam temo.
Zadnjih 15 let supportiram igralniške naprave po vsem svetu, ki uporabljajo floating, pa nisem še imel pritožbe, da bi kdo imel višek ali manjko (niti centa) glede na online sistem.
Ne pravim, da jype nima prav, načeloma se strinjam z njim, ampak včasih je dobro furat herezijo. ;)
Zgodovina sprememb…
- spremenil: YaN-cH ()
kuall ::
Tudi jaz poznam nek zelo uspešen program, ki uporablja float za denar ponekod. Ta program je tudi razlog, zakaj sem jaz uporabil float, ker sem ga posnemal.
float v MSSQL je bolj natančen kot pa v MYSQL se mi zdi. zakaj že?
float v MSSQL je bolj natančen kot pa v MYSQL se mi zdi. zakaj že?
kuall ::
V MSSQL je čist ok, če zapišeš denar v FLOAT, mislim končno vrednost, ne vmesno, ko preračunavaš. To pa zato, ker moraš denar zapisat do centa natančno, to pomeni na 2 decimalni mesti natačno. FLOAT v MSSQL pa to vedno prav shrani. Dokaz so programi, ki uporabljajo float za shranjevanje denarja in imajo na milijone uporabnikov brez pritožb o napakah. V MYSQL pa po mojih testih že ni OK. Od kod razlika med bazama ne vem zdajle.
Ne jypeta poslušat. On samo lima linke in ponavlja za teksti, ki jih je prebral, pa še to slabo. Prakse nima pa nobene. Lastnega razumevanja pa še manj.
Ne jypeta poslušat. On samo lima linke in ponavlja za teksti, ki jih je prebral, pa še to slabo. Prakse nima pa nobene. Lastnega razumevanja pa še manj.
Zgodovina sprememb…
- spremenilo: kuall ()
holabaluza ::
V MSSQL je čist ok, če zapišeš denar v FLOAT, mislim končno vrednost, ne vmesno, ko preračunavaš.
a ni to ravno bistveni problem pri floating point? Pojavijo se problemi, kadar izvajas racunske operacije. Programi, ki se drzijo IEEE standarda nebi smel problem razbrat konstantno vrednost.
Zgodovina sprememb…
- spremenilo: holabaluza ()
MH0 ::
declare @f float declare @d decimal(19,5) set @f = 2.0 set @d = 2.0 select @f + 0.01 - @f, @d + 0.01 - @d
kuall ::
Saj že ko narediš
declare @f float = 1.1
v resnici narediš tole:
declare @f float = 1.10000002384185791015625
samo ne vem zakaj potem ko narediš select @f ne prikaže druge vrednosti ampak prvo?
Lej, stvar je takale: float že v osnovi ko narediš enostaven assignment ne shrani vrednosti, ki si jo ti določil ampak shrani neko vrednost, ki je malenkost drugačna, bi rekel da v več kot 90% primerih ne shrani točne vrednosti. Od tod pridejo potem vse napake. ne od samega računanja. pri računanjau se napake samo povečajo zaradi teh originalnih napak, ker ne moreš shranit točne vrednosti v float, ker je bistvo floata to, da je skoraj vedno shranjen približek.
declare @f float = 1.1
v resnici narediš tole:
declare @f float = 1.10000002384185791015625
samo ne vem zakaj potem ko narediš select @f ne prikaže druge vrednosti ampak prvo?
holabaluza je izjavil:
a ni to ravno bistveni problem pri floating point? Pojavijo se problemi, kadar izvajas racunske operacije. Programi, ki se drzijo IEEE standarda nebi smel problem razbrat konstantno vrednost.
Lej, stvar je takale: float že v osnovi ko narediš enostaven assignment ne shrani vrednosti, ki si jo ti določil ampak shrani neko vrednost, ki je malenkost drugačna, bi rekel da v več kot 90% primerih ne shrani točne vrednosti. Od tod pridejo potem vse napake. ne od samega računanja. pri računanjau se napake samo povečajo zaradi teh originalnih napak, ker ne moreš shranit točne vrednosti v float, ker je bistvo floata to, da je skoraj vedno shranjen približek.
Zgodovina sprememb…
- spremenilo: kuall ()
Utk ::
Ko pa delaš kalkulacije pa moraš money ali float pretvorit v decimal
Pa boš to res naredu pri vsakem računanju? Si siguren, da boš? Da se že v štartu zavedaš problema in ga greš "rešit" na tak način, da boš pač "zmeraj" nekaj naredu, je kolosalna neumnost. To ni rešitev, ampak vzrok problemov, ki si jih ne boš rešil NIKOLI.
kuall ::
Itak uporabiš za denar decimal (19, 6) pa adijo. Najbolj varno. MONEY ima spet neke svoje fore.
Ampak če imaš že obstoječ program, ki uporablja float se greš to.
Ampak če imaš že obstoječ program, ki uporablja float se greš to.
Spura ::
Kok je tukaj enih ljudi, ki mislijo da so samo racunske operacije problem, storage pa ne.
Dej probaj izpisat nasledn 32-bit float: 167772.18 -> dobis 167772.19
Ali pa 16777217 konvertiraj v float 32 -> dobis 16777218
Ali pa bolj banalen primer: 0.1f je ubistvu 0.100000001490116119384765625.
Ne rabis nobene aritmetike za napake.
Dej probaj izpisat nasledn 32-bit float: 167772.18 -> dobis 167772.19
Ali pa 16777217 konvertiraj v float 32 -> dobis 16777218
Ali pa bolj banalen primer: 0.1f je ubistvu 0.100000001490116119384765625.
Ne rabis nobene aritmetike za napake.
Looooooka ::
V svetu, ki gre na kriptovalute, kjer je procesorska moc in spomin cedalje cenejsa bi sparali na spominu in se izogibali decimalkam.
OK...prosim ce nas v naprej obvestite o programu, da se mu lahko na dalec izognemo v kolikor bo povezan s financami :)
OK...prosim ce nas v naprej obvestite o programu, da se mu lahko na dalec izognemo v kolikor bo povezan s financami :)
Vredno ogleda ...
Tema | Ogledi | Zadnje sporočilo | |
---|---|---|---|
Tema | Ogledi | Zadnje sporočilo | |
» | Linux 4.10 je tu (strani: 1 2 )Oddelek: Novice / Operacijski sistemi | 14813 (11542) | BigWhale |
» | Kako zaokrožiti? Cena brez davka + popust + DDV decimalkeOddelek: Programiranje | 4418 (3575) | kunigunda |
» | java Double.valueOfOddelek: Programiranje | 1426 (1320) | Spura |
» | Mnozenje float stevil (C)Oddelek: Programiranje | 1571 (1234) | Isotropic |
» | [Python] Deljenje stevila v obliko xE+yOddelek: Programiranje | 1617 (1405) | Jean-Paul |