Builder.cz - Informacni server o programovani

Odběr fotomagazínu

Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!

 

Zadejte Vaši e-mailovou adresu:

Kamarád fotí rád?

Přihlas ho k odběru fotomagazínu!

 

Zadejte e-mailovou adresu kamaráda:



Float - Double - BigDecimal

Seznam témat     Nová odpověď

Přihlásit se     Registrace     Zapomenuté heslo

Re: Float - Double - BigDecimal

Autor: Maaartin

14:55:06 22.08.2011

> [ital]Dej si pozor aby oba BigDecimal mely v konstruktoru String, pak to bude
AFAIK ok.[/ital]

Urcite, ale takhle to mam schvalne: Pocitam rozdil mezi 0.1 a jeho double reprezentaci.

> [ital]Máš pravdu, napsal jsem něco jiného než jsem chtěl. Furt se motáme kolem toho, že to není přesně. Asi bylo téma dost vyčerpáno a já se musím už jenom opakovat [/ital]

Fajn. Ja hlavne zkousel obhajit moje rozhodnuti ho nepouzivat (teda vzhledem k problemum s packalem mi stejne nic jinyho nezbylo).

Citovat příspěvek

 

Re: Float - Double - BigDecimal

Autor: jura.polak

13:42:36 22.08.2011

> Takze chybu mam, ale v radu trilionstin.

Máš pravdu, napsal jsem něco jiného než jsem chtěl. Furt se motáme kolem toho, že to není přesně. Asi bylo téma dost vyčerpáno a já se musím už jenom opakovat :-)

Citovat příspěvek

 

Re: Float - Double - BigDecimal

Autor: nkd

13:28:37 22.08.2011

> Od: "Maaartin"
> To jsem nepochopil:
> System.out.println(new BigDecimal("0.1").subtract(new
BigDecimal(0.1)));

Dej si pozor aby oba BigDecimal mely v konstruktoru String, pak to bude
AFAIK ok.

NkD

Příspěvek zaslán emailem

Citovat příspěvek

 

Re: Float - Double - BigDecimal

Autor: Maaartin

13:20:21 22.08.2011

> [ital]Když uložíš do decimalu 0.1, tak je to přesně. V double se to ale nedá přesně uložit, takže máš chybu už v prvním řádu desetin.[/ital]

To jsem nepochopil:
System.out.println(new BigDecimal("0.1").subtract(new BigDecimal(0.1)));

vypise
-5.5511151231257827021181583404541015625E-18
Takze chybu mam, ale v radu trilionstin.

> [ital]A když to v double zaokrouhlíš na desetiny (v desítkové soustavě), tak to zase nemáš přesně, ale jenom přibližně.[/ital]

No, nemam, treba
final double x = 0.1-0.04-0.06;
System.out.println(x);
vypise
6.938893903907228E-18
ale kdyz to zaokrouhlim treba na 6 mist
System.out.println(Math.round(1e6*x) / 1e6);
tak mam zase 0.0.

Citovat příspěvek

 

Re: Float - Double - BigDecimal

Autor: jura.polak

12:21:30 22.08.2011

> pokud ho v MySql zadeklarujes jako DECIMAL(41, 40), tak pro nej potrebujes 19 bajtu. Normalne predem nevis s jakymi cisly budes pocitat, takze to bude vypadat trochu jinak.

Když děláš finanční aplikace, tak používáš zpravidla dec(2) někdy i jiné přesnosti, např. 4, ale hlavní problém double oproti decimalu je jinde. Když uložíš do decimalu 0.1, tak je to přesně. V double se to ale nedá přesně uložit, takže máš chybu už v prvním řádu desetin. A když to v double zaokrouhlíš na desetiny (v desítkové soustavě), tak to zase nemáš přesně, ale jenom přibližně.

Citovat příspěvek

 

Re: Float - Double - BigDecimal

Autor: Maaartin

11:37:48 22.08.2011

Tvuj presny vysledek 1.4394823447349446374031355936828402124201 ma 41 platnych cislic a pokud ho v MySql zadeklarujes jako DECIMAL(41, 40), tak pro nej potrebujes 19 bajtu. Normalne predem nevis s jakymi cisly budes pocitat, takze to bude vypadat trochu jinak.

Muj nepresny vysledek 1.4394823447349436 zabira 8 bajtu a ma absolutni chybu 1.00667681518656232927663671376953125e-15. Relativni chyba je skoro stejny prd. Takze jsi sice ziskal za cenu zdvojnasobeni pameti (coz v DB muze znamenat polovicni rychlost a v Jave je to jeste horsi) naprosto presny vysledek, ale ten doublovsky je nemeritelne horsi.

> [ital]Uvedený příklad je samozřejmě nesmysl, protože každý rok se počítá úrok jenom jednou a aktuální saldo se musí uložit do databáze. A to buď jako zmršené přibližné číslo v reálném typu anebo jako přesné číslo zaokrouhleno na určitý počet desetinných míst v decimalu.[/ital]

Mas pravdu v tom ze takhle se to dela, takze muj priklad neni realny. My tam ale pocitame neco jinyho kde zadny takovy zaokrouhlovani predepsany neni.

Pokud je predepsany zaokrouhlovani na miliontiny, paxe dostanu s double na presne stejny vysledek, viz
http://dl.dropbox.com/u/4971686/110822/RoundingDemo.java

Ja netvrdim ze DECIMAL/BigDecimal je spatny, jen ze je precenovany. Pokud mas presne predepsany co musi vyjit, tak jo. Pokud ti nezalezi na rychlosti ani na spotrebe pameti, tak klidne. Pokud vis v jakym rozsahu se tvoje cisla pohybuji, tak mozna. Pokud te nepatrny odchylky neirituji, tak je zbytecny. Pro presny "vedecky" vypocty snad (neni nejrychlejsi).

> [ital]A jinak - původně to mělo asi dokumentovat, že double je přesnější.[/ital]

Ne, double rozhodne neni presnejsi nez BigDecimal, to nejde. Ale muze byt presnejsi nez DECIMAL.

PS: Pro 6 desetinnych mist jsem musel pouzit
private final MathContext mc = new MathContext(7);
Nejaxem tam nenasel jak pocitat s 6 misty za desetinnou teckou.

Citovat příspěvek

 

Re: Float - Double - BigDecimal

Autor: jura.polak

10:14:01 22.08.2011

A jinak - původně to mělo asi dokumentovat, že double je přesnější. Proto jsem naimplementoval obě funkce Power stejně a nepoužil jinou implementaci, aby bylo vidět, že se jedná o totožný výpočet. Jenom aby se vidělo, co počítá dobře a co hodnoty mrší.

Citovat příspěvek

 

Re: Float - Double - BigDecimal

Autor: jura.polak

10:04:27 22.08.2011

> Co uvedený příklad dokumentuje? Že v běžných podmínkách je to jedno? Není.

To se zeptej Maartina, ten chctěl, abych to zkusil ;-)

Uvedený příklad je samozřejmě nesmysl, protože každý rok se počítá úrok jenom jednou a aktuální saldo se musí uložit do databáze. A to buď jako zmršené přibližné číslo v reálném typu anebo jako přesné číslo zaokrouhleno na určitý počet desetinných míst v decimalu.

Citovat příspěvek

 

Re: Float - Double - BigDecimal

Autor: v

9:40:55 22.08.2011

Co uvedený příklad dokumentuje? Že v běžných podmínkách je to jedno? Není.
I při běžných výpočtech s double je dobré postup operací optimalizovat tak, aby se řád mezivýsledků měnil jen minimálně.

BigDecimal 1.0371 ^ 10 = 1.4394823447349446374031355936828402124201
Double 1.0371 ^ 10 = 1.4394823447349436

Citovat příspěvek

 

Re: Float - Double - BigDecimal

Autor: jura.polak

8:24:36 22.08.2011

Sorry, blbě jsem přečetl zadání.
Volání mělo být správně takhle
int i = 10;
System.out.println(("BigDecimal 1.0371 ^ " + i + " = " + bPower(new BigDecimal("1.0371"), i)));
System.out.println(("Double 1.0371 ^ " + i + " = " + dPower(1.0371, i)));

a výsledek:
BigDecimal 1.0371 ^ 10 = 1.4394823447349446374031355936828402124201
Double 1.0371 ^ 10 = 1.4394823447349436

Citovat příspěvek

 

Re: Float - Double - BigDecimal

Autor: jura.polak

8:21:58 22.08.2011

> Zkus spocitat muj vyse uvedeny "Jednoduchy priklad: Na kolik naroste jedna kacka kocourkovska za 10 let pri urocich 3.71% rocne?" a paxi rekneme jak uzitecny je DECIMAL.

Myslíš takhle?

int i = 10;
System.out.println(("BigDecimal 3.71 ^ " + i + " = " + bPower(new BigDecimal("3.71"), i)));
System.out.println(("Double 3.71 ^ " + i + " = " + dPower(3.71, i)));

private static double dPower(double aDv, int aI) {
if (aI == 1) return aDv;
return aDv * dPower(aDv, aI - 1);
}

private static BigDecimal bPower(BigDecimal aBv, int aI) {
if (aI == 1) return aBv;
return aBv.multiply(bPower(aBv, aI - 1));
}

Výsledek:
BigDecimal 3.71 ^ 10 = 494013.81738478419529024201
Double 3.71 ^ 10 = 494013.81738478417

Na tom double je divný, že nekončí jedničkou - přesně spočítaný výsledek násobení čísel, která mají na konci 1, musí končit jedničkou. :)

Citovat příspěvek

 

Re: Float - Double - BigDecimal

Autor: v

10:46:07 21.08.2011

v seriozních finančních aplikacích se formát double skutečně nepoužívá.

Citovat příspěvek

 

Re: Float - Double - BigDecimal

Autor: Mi.Chal

10:35:05 21.08.2011

Maaartin Napsal:
-------------------------------------------------------
> S tim vzrustanim nepresnosti je to s prominutim
> pekna blbost (tim nescu rict, ze cim vic operaci
> tim bude vysledek presnejsi). Chyba roste ale
> pomalu a da se lehce spocitat jeji mez. Nekam do
> relevantnich hodnot se muze dostat az za hodne
> dlouho, ledaze bys delal numericky nestabilni
> vypocty. Paxi ale s DECIMAL nahrany jeste vic.

ono je pri vypoctech vetsinou definovany, na kolik desetinnych mist mas pocitat, takze u vsech hodnot mas treba 4 desetinna mista a dal nuly. U float tohle u vsech cisel proste neudelas, protoze to tam neulozis presne, tam mas vzdycky tech 15-16 nebo kolik mist, v zavislosti na presnosti.

Citovat příspěvek

 

Re: Float - Double - BigDecimal

Autor: Maaartin

4:35:03 21.08.2011

> [ital]ja nekde videt double, tak me spis nejdriv napadne, ze tu db delal nekdo, kdo se pred tydnem zacal ucit php a mysql :-).[/ital]

Zdani klame. Ja se php jeste ani ucit nezacal.

> [ital]Pokud by se taková čísla používala ve výpočtech, vedlo by to k vzrůstání nepřesnosti a občas by se lidi divili...[/ital]

Zkus spocitat muj vyse uvedeny "Jednoduchy priklad: Na kolik naroste jedna kacka kocourkovska za 10 let pri urocich 3.71% rocne?" a paxi rekneme jak uzitecny je DECIMAL.

S tim vzrustanim nepresnosti je to s prominutim pekna blbost (tim nescu rict, ze cim vic operaci tim bude vysledek presnejsi). Chyba roste ale pomalu a da se lehce spocitat jeji mez. Nekam do relevantnich hodnot se muze dostat az za hodne dlouho, ledaze bys delal numericky nestabilni vypocty. Paxi ale s DECIMAL nahrany jeste vic.

Citovat příspěvek

 

Re: Float - Double - BigDecimal

Autor: jura.polak

21:57:07 20.08.2011

Záleží na použití. Jestli se má pracovat v desítkové soustavě a ukládána mají být čísla také v desítkové soustavě, tak jedině decimal. Zejména pokud se má pracovat s částkami, tak nikdy nic jiného než decimal. Pseudoreálné typy nejsou podle mého v podstatě k ničemu dobré ;-)

Důvody - to je matematika základní, možná střední školy. Stačí, když si člověk uvědomí, že ve dvojkové soustavě desetinná čísla nelze uložit přesně. Např. číslo 0.65 má ve dvojkové soustavě periodický rozvoj (http://forum.builder.cz/read.php?14,2831232,2833399#msg-2833399), do floating pointu tedy nelze uložit přesně, ale zaokrouhleně. V decimalu je samozřejmě uloženo přesně. Pokud by se taková čísla používala ve výpočtech, vedlo by to k vzrůstání nepřesnosti a občas by se lidi divili (A taky už se divili - používáme v práci Jasper Print, nějaký dobrák použil v šablonách Double, potom se zákazník divil, že jsou v reportu v částkách chyby. Tak nešťastník předělával na pracnější, ale správný BigDecimal a problém tím odstranil).

Citovat příspěvek

 

Re: Float - Double - BigDecimal

Autor: Mi.Chal

20:35:00 20.08.2011

Maaartin Napsal:
-------------------------------------------------------
> DOUBLE v DB pouzivam ze dvou duvodu:
>
> - S DECIMAL byl v Delphi naky problem, je to samy
> bug.

Delphi uz jsem par let nepouzil, je to mozne

> - Nikdo mi nebyl schopny rict, jaky velikosti ty
> cisla nabyvaji. Sloupce jsou casto pojmenovany
> blbe (jedna se o prevzaty data, kde casto netusim
> wo co go), jejich popisu se da verit asi jako
> predpovedim klimatu. Pouzivat vsude naky obrovsky
> DECIMAL(40, 20) se mi vazne nesce.

mozna by to bylo porad lepsi nez tam mit cisla jako 5 biliontin

> Takze DOUBLE je pro me bezpecna volba.

ja nekde videt double, tak me spis nejdriv napadne, ze tu db delal nekdo, kdo se pred tydnem zacal ucit php a mysql :-). Me se jeste nestalo, ze bych tyhle typy v db nekdy potreboval

Citovat příspěvek

 

Re: Float - Double - BigDecimal

Autor: Maaartin

19:26:57 20.08.2011

S tim souhlasim, zakaznik se taky divil kdyz nekde v DB videl 5.24156441e-13. Vysvetlil jsem mu ze je to celkem presne nula a bylo to v pohode. Program nastesti nic takovyho neukazal (tam se to zaokrouhli), vysvetlovat to jeho zakaznikum by neslo.

DOUBLE v DB pouzivam ze dvou duvodu:

- S DECIMAL byl v Delphi naky problem, je to samy bug.
- Nikdo mi nebyl schopny rict, jaky velikosti ty cisla nabyvaji. Sloupce jsou casto pojmenovany blbe (jedna se o prevzaty data, kde casto netusim wo co go), jejich popisu se da verit asi jako predpovedim klimatu. Pouzivat vsude naky obrovsky DECIMAL(40, 20) se mi vazne nesce.

Takze DOUBLE je pro me bezpecna volba.

Citovat příspěvek

 

Re: Float - Double - BigDecimal

Autor: Mi.Chal

19:13:11 20.08.2011

Maaartin Napsal:
-------------------------------------------------------
> Me osobne by bilion kacek stacil. Snad.

nasi vlade by to nestacilo ani na zamaznuti dluhu, co nam nasekala.

Myslim, ze u float je hlavni problem v tom, ze ta presnost neni nijak presne vymezena, proste je platnych par mist a nekde dal se to rozsype a muze tam byt cokoliv. U databazovych typu jako decimal clovek rekne, ze chce presnost na x mist a ma ji, dal jsou nuly a po operacich s decimaly se tam neobjevi nejake cislice navic.

Citovat příspěvek

 

Re: Float - Double - BigDecimal

Autor: Maaartin

15:47:27 20.08.2011

No ono vetsinou sces aby to bylo zaokrouhleny vsecko stejne, protoze kdyz mas pod sebou cisla jako

123.456
7.89012
34567.0

tak tezko poznas ktery je vetsi. Mam pocit, ze DecimalFormat zaokrouhlovani na naky pocet platnych cislic neumi. Nejaky ChoiceFormat by mozna pomohl, ale spis ne (mel bys tam jeden pripad pro kazdy pocet nul za desetinnou teckou). Napsat si sam by nemel byt problem.

Citovat příspěvek

 

Re: Float - Double - BigDecimal

Autor: johny003

15:23:21 20.08.2011

uh tak díky za odpovědi..video je poučný a zajímavý dík:)

ještě teda o tom trochu popřemýšlím..ale přecejenom ta přesnost není AŽ TAK kritická a nakonec jsem se rozhodl ty hodnoty zaokrouhlovat na 2-3 desetinná místa..tudíž snad v takovém řádu by se ta nepřesnost u doublu měla ztratit..hm?

A ještě jeden dotaz už trošku offtopic..týká se zaokrouhlování..
Normálně bych chtěl zaokrouhlovat čísla na 2-3 desetinná místa..ale např. číslo 0,00003 mi to zaokrouhlí na 0, ale já bych chtěl zachovat minimálně tu jednu platnou číslici..zkoušel jsem si různě hrát s DecimalFormatem ale nemůžu přijít jak hezky na to..nemá s tím někdo zkušenost?..poslední varianta je, že u atributů, kde podobnou hodnotu očekávám, to zformátuju jiným DecimalFormatem, který to zaokrouhlí na víc míst..ale to je takový záložní řešení..

Citovat příspěvek

 

Re: Float - Double - BigDecimal

Autor: Maaartin

23:41:36 19.08.2011

> [ital]Double má sice obecně velký rozsah a přesnost, ale kvůli tomu, jak funguje pohyblivá řádová čárka, nedokáže určitá čísla reprezentovat přesně. A rozhodně to nemusí být nějaké obskurní číslo s x desetinnými místy, jeden příklad za všechny:
System.out.println(2.0 - 1.1)[/ital]

Ve dvojkove soustave je daji vyjadrit presne jen cisla ktery jdou ziskat z celyho cisla opakovanym delenim dvema. V desitkove soustave daji vyjadrit presne jen cisla ktery jdou ziskat z celyho cisla opakovanym delenim deseti. Takze jeden priklad za vsechny:

System.out.println(1.0 / 3);

Samozrejme uznavam ze co tady pisu je demagogie, protoze na vstupu bude normalne cislo vyjadreny desitkove. Ale stejne, jsou v podstate dve moznosti:

Bud s temi cisly nepocitas a paxtaci vysledek typu double zaokrouhlit na tolik mist kolik jich to ma mit. Nebo s nima pocitas, a pak mas problem s obojim. Jednoduchy priklad: Na kolik naroste jedna kacka kocourkovska za 10 let pri urocich 3.71% rocne?

Citovat příspěvek

 

Re: Float - Double - BigDecimal

Autor: Maaartin

23:30:01 19.08.2011

> [ital]nevim co je silene presny, ale ta presnost je necelych 16 dekadickych mist (viz http://en.wikipedia.org/wiki/IEEE_754-2008), coz pozadavek tazatele uz moc nesplnuje, kdyz pise o 16 mistech.[/ital]

No... ma tam 16 mist, protoze pouziva NUMERIC. Kdyz pocitas s bilionama kacek, tak mas 13 mist pred desetinou teckou a presnost na desetinu halire. Chapu ze to nekomu nestaci...

Me osobne by bilion kacek stacil. Snad.

> [ital]myslim ze treba na ukladani peneznich castek nikdo normalni double pouzivat nebude.[/ital]

Ja netvrdim ze su normalni.

> [ital]V databazich mi taky prijde castejsi pouzivani fixed point typu jako decimal nez tech floating point.[/ital]

To ma aspon dva duvody:
- Dela se tam s fixed point pohodlne, proste pises A+B at je to co je to.
- Na rychlosti aritmetiky tam moc nezalezi.

Citovat příspěvek

 

Re: Float - Double - BigDecimal

Autor: Natix

23:13:47 19.08.2011

Double má sice obecně velký rozsah a přesnost, ale kvůli tomu, jak funguje pohyblivá řádová čárka, nedokáže určitá čísla reprezentovat přesně. A rozhodně to nemusí být nějaké obskurní číslo s x desetinnými místy, jeden příklad za všechny:
[code]System.out.println(2.0 - 1.1);[/code]
vytiskne 0.8999999999999999.

Čili v případě, že mi nestačí přibližné hodnoty nebo nechci zaokrouhlovat, tak je nutností BigDecimal. U něj ovšem pozor, pokud použiješ konstruktor
[code]new BigDecimal(double)[/code]
tak se vytvoří BigDecimal s přesně stejnou hodnotou jako předaný double, čili nejen že problém nevyřešíš, ale dokonce jeho vytisknutím dostaneš číslo ještě mnohem delší. Buď je třeba používat konstruktor
[code]new BigDecimal(String)[/code]
nebo statickou metodu
[code]BigDecimal.valueOf(double)[/code]
Josh Bloch měl na tohle téma docela pěkný puzzler ve své přednášce na letošním Google I/O (hned ten první).
http://www.youtube.com/watch?v=wbp-3BJWsU8

Citovat příspěvek

 

Re: Float - Double - BigDecimal

Autor: Mi.Chal

21:40:07 19.08.2011

Maaartin Napsal:
-------------------------------------------------------
> Ufff.. double je silene presny a staci na
> vsecko... pokud ovsem zakaznik neprska ze se mu
> namisto 0 vypisuje 4.547473508864641E-13. Pokud
> vsecky vysledky zobrazis rozumne zaokrouleny, paxe
> rozdil nepozna. Teda obvykle...

nevim co je silene presny, ale ta presnost je necelych 16 dekadickych mist (viz http://en.wikipedia.org/wiki/IEEE_754-2008), coz pozadavek tazatele uz moc nesplnuje, kdyz pise o 16 mistech. Uz na tom sestnactem miste muze mit nekdy chybu a kdyz bude delat nejakou operaci s dvemi takovymi cisly, tak to presnosti vysledku moc neprospeje

> Existuji vypocty kde se sebemensi chybka muze
> libovolne zvetsovat, pak je treba pocitat s
> presnymi cisly, pokud se ovsem da. Ja osobne zadny
> takovy pripad (kde by bylo splneno oboje) neznam.

myslim ze treba na ukladani peneznich castek nikdo normalni double pouzivat nebude. V databazich mi taky prijde castejsi pouzivani fixed point typu jako decimal nez tech floating point

Citovat příspěvek

 

Re: Float - Double - BigDecimal

Autor: Maaartin

18:27:07 19.08.2011

Ufff.. double je silene presny a staci na vsecko... pokud ovsem zakaznik neprska ze se mu namisto 0 vypisuje 4.547473508864641E-13. Pokud vsecky vysledky zobrazis rozumne zaokrouleny, paxe rozdil nepozna. Teda obvykle...

Existuji vypocty kde se sebemensi chybka muze libovolne zvetsovat, pak je treba pocitat s presnymi cisly, pokud se ovsem da. Ja osobne zadny takovy pripad (kde by bylo splneno oboje) neznam.

Pri pouziti double nesmis porovnavat pomoci "==" ale vzdy je treba nechat nejakou toleranci. Staci opravdu malicka.

Osobne povazuju BigDecimal za v podstate zbytecny, sice ulehci praci ale double je mnohem rychlejsi (coz je vetsinou uplne jedno!) a pohodlnejsi (kdyz nemame operator-overloading).

Citovat příspěvek

 

Float - Double - BigDecimal

Autor: johny003

18:04:16 19.08.2011

Zdravím,
řeším ve svém projektu, jaký číselný typ hodnot použít.. nejprve jsem zvolil v DB (postgresql) real a v aplikaci Float..ale to se ukázalo jako dosti nepřesné..teď používám v DB numeric a v aplikaci Double..hodnoty sčítám a vyžaduji přesnost nasčítaných údajů..ty se pohybují ve výsledku(myslím už ty součty) v cca 10 číslicích před desetinnou čárkou a asi 6 číslicích za desetinnou čárkou..co jsem se snažil tak pročítat o Doublu v javě, tak si myslím, že by to stačit mělo a BigDecimal nebude potřeba..ale moc se v těchhle typech nevyznám, radši se tu zeptám odborníků:) kdy použít už BigDecimal a kdy mi postačí ještě Double..?

Díky za odpověď.
Honza

Citovat příspěvek

 

 

 

Přihlášení k mému účtu

Uživatelské jméno:

Heslo: