Diskuze: Finance

Podnikání a výdělek na internetu Finance

Avatar
Adam "Nero" Chudomel:

Ahoj, mám dělat finanční systém ale nevím jakým jazykem, protože když se pro nějaký rozhodnu tak okamžitě znejistiím protože mě napadne Miliardy důvodů proč ne ... Jaký jazyk má v číslech nejméně nesrovnalostí, případně jaký datový typ ... Díky!

Odpovědět 15.5.2014 11:09
Nihil est, aut totum licet consistere
Avatar
Odpovídá na Adam "Nero" Chudomel
Luboš Běhounek (Satik):

MSSQL + C# má typ Decimal, který se na tyhle věci hodí, protože u něj nedochází ke ztrátě přesnosti.
Jak jsou na tom ostatní jazyky netuším, ale určitě to bude možné nahradit alespoň nějakou knihovnou, pokud nemají nějakou obdobu.

Nahoru Odpovědět 15.5.2014 11:15
:)
Avatar
coells
Redaktor
Avatar
Odpovídá na Luboš Běhounek (Satik)
coells:

I u typu Decimal dochází ke ztrátě přesnosti - a už z principu neexistuje typ, kde by nedocházelo. Jenom je těžší si ho všimnout díky fixní řádové čárce a vyššímu počtu desetinných míst. Z toho důvodu se finanční výpočty vždy počítají v celých čísel.

 
Nahoru Odpovědět 15.5.2014 11:39
Avatar
Odpovídá na coells
Luboš Běhounek (Satik):

Ale nedochází :) (samozřejmě pokud nezadáš číslo mimo rozsah nebo s více než 28 číslicemi).
Decimal je právě uložený jako celé číslo s desítkovým exponentem a je určený pro práci s financemi.

Nahoru Odpovědět 15.5.2014 11:55
:)
Avatar
coells
Redaktor
Avatar
Odpovídá na Luboš Běhounek (Satik)
coells:

The Decimal value type represents decimal numbers ranging from positive 79,228,162,51­4,264,337,593,543,950,335 to negative 79,228,162,51­4,264,337,593,543,950,33­5. The Decimal value type is appropriate for financial calculations that require large numbers of significant integral and fractional digits and no round-off errors. The Decimal type does not eliminate the need for rounding. Rather, it minimizes errors due to rounding. For example, the following code produces a result of 0.99999999999­99999999999999999 instead of 1.

Trik je v tom, že se používá 128 bitů místo 64 a mantisa má více bitů na úkor exponentu, aby se posunula hranice zaokrouhlovací chyby. Takže chyby jsou vzácnější, ale stále s nimi musíš počítat.

 
Nahoru Odpovědět 15.5.2014 12:02
Avatar
coells
Redaktor
Avatar
Odpovídá na coells
coells:

Až budeš psát nějaký finanční systém, tak si dej pozor na prvočíselný počet dní v měsíci a nesoudělnost. Když jsem dělal za ekonomickém sw, hledali jsme takovou chybu dlouho.

Navíc je v téhle části zákon nejasný, a když ti účetní kontroluje výsledky, dojdete ke odlišným výsledkům - a oba budou správně. :-) Ve výsledku decimal vůbec nic neřeší.

 
Nahoru Odpovědět 15.5.2014 12:09
Avatar
Odpovídá na coells
Luboš Běhounek (Satik):

S tou nepřesností jsem to myslel jinak než ty - ne u výpočtů, ale už při ukládání (a případně základních operací).
Ve finančnictví se používá desítková soustava a Decimal používá jako základ pro exponent taky 10, takže při ukládání hodnot, které jsou v desítkové soustavě bez period nebo neukončených desetinných rozvojů nedochází ke ztrátě přesnosti, narozdíl od běžného floatu (který má základ 2).

Např. v následujícím kódu:

float a = 0.3f;
      float b = 0.2f;
      float c = 0.5f;
      if ((a + b) == c)
        Console.WriteLine("true");
      else
        Console.WriteLine("false");
      Console.WriteLine(a + b);
      Console.WriteLine(c);

, který vypíše:

false
0,5
0,5

tedy že 0,5 != 0,5.

Pokud samozřejmě do Decimalu uložíš číslo, které uložit nedokáže, tak tam tu přesnost ztratí.

Editováno 15.5.2014 12:56
Nahoru Odpovědět 15.5.2014 12:53
:)
Avatar
Jan Vargovský
Redaktor
Avatar
Odpovídá na Luboš Běhounek (Satik)
Jan Vargovský:

Do konzole můžeš vypsat přímo bool a napíše ti to True/ False :)

 
Nahoru Odpovědět 15.5.2014 13:05
Avatar
coells
Redaktor
Avatar
Odpovídá na Luboš Běhounek (Satik)
coells:

Právě, že to je omyl, protože decimal funguje zcela stejně jako float.

Zaměstnanec pracuje denně 8 hodin, 20 dní v měsíci a máš 10 zaměstnanců.
8 * 20 * 10 = 1600

Takže řekněme že čísla do 2000 jsou zcela běžná.
Teď už je snadné parafrázovat tvůj příklad protipříkladem.

decimal a = 3m / 1121m;
decimal b = 2m / 1121m;
decimal c = 5m / 1121m;

Console.WriteLine(a + b == c);

Jak říkám, psal jsem ekonomický sw a decimal ve srovnání s double nic neřeší.

 
Nahoru Odpovědět 15.5.2014 13:32
Avatar
coells
Redaktor
Avatar
Odpovídá na Luboš Běhounek (Satik)
coells:

Ještě mě napadl případ, který se nám opravdu stával.

Počítáš mzdu podle zákona, který uvádí vzorec pro výpočet s poznámkou, že poté se částka zaokrouhlí na koruny směrem dolů. V tomhle případě jsme dostávali dva výsledky v lehce odlišných situacích. Nakonec jsme zjistili, že v jednom případě vyšla částka 1000,000....001 zatímco ve druhém 999.999....999

Zaokrouhlení dolů pak dá rozdíl jednu korunu, která se ve výsledku jeví jako chyba.

Řešení? Používat decimal pro jednotlivé operace a mezivýsledky zaoukrouhlovat z 28 míst na 25. Jenže zákon, který se o zaoukrohlování zmiňuje, říká, že tohle bys dělat neměl (v zákoníku je to trochu nejednoznačné, ale spíše ne).

Jiné řešení? Banky vždy počítaly pouze v celých číslech na 4-8 míst s fixní řádovou čárkou, a protože se dělí v celých číslech, zbytky po dělení se ignorují.

 
Nahoru Odpovědět 15.5.2014 13:43
Avatar
Lako
Člen
Avatar
 
Nahoru Odpovědět 16.5.2014 16:10
Avatar
Odpovídá na Lako
Luboš Běhounek (Satik):

Ne, to v desítkové soustavě nezapíšeš na omezeném prostoru přesně.

Nahoru Odpovědět 16.5.2014 16:25
:)
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 13 zpráv z 13.