it-swarm-eu.dev

Použít float nebo desetinné číslo pro účetnictví částku?

Přepisujeme náš starší účetní systém ve VB.NET a SQL Serveru. Přinesli jsme nový tým .NET/SQL programátorů k přepsání. Většina systému je již doplněna částkou Dollar s použitím Floats. Původní systémový jazyk, který jsem naprogramoval, neměl plovák, takže bych pravděpodobně použil desetinné místo.

Jaké je vaše doporučení?

Měly by být pro dolarové částky použity plovoucí nebo desítkové datové typy?

Jaké jsou některé z kladů a záporů?

Jeden Con zmínil se v našem každodenním scrum byl vy musíte být opatrný když vy počítáte částku, která vrací výsledek, který je přes dvě desetinná místa. Zní to, že budete muset zaokrouhlit částku na dvě desetinná místa.

Další Con je všechny displeje a tištěné částky musí mít formát prohlášení, které ukazuje dvě desetinná místa. Všiml jsem si několikrát, kde to nebylo hotovo a částky nevypadaly správně. (tj. 10,2 nebo 10,2546)

Pro je Float trvá pouze 8 bajtů na disku, kde desetinné místo zabírají 9 bajtů (desetinné číslo 12,2) 

74
Gerhard Weiss

Měly by být pro dolarové částky použity plovoucí nebo desítkové datové typy?

Odpověď je snadná. Nikdy plave. NIKDY!

Plováky byly podle IEEE 754 vždy binární, pouze nové standardy IEEE 754R definované dekadické formáty. Mnoho zlomkových binárních částí nemůže nikdy odpovídat přesné dekadické reprezentaci.
Jakékoliv binární číslo může být zapsáno jako m/2^n (m, n pozitivní celá čísla), libovolné desetinné číslo jako m/(2^n*5^n).
Jak binární soubory postrádají prime factor 5, všechna binární čísla mohou být přesně reprezentována desetinnými místy, ale ne naopak.

0.3 = 3/(2^1 * 5^1) = 0.3

0.3 = [0.25/0.5] [0.25/0.375] [0.25/3.125] [0.2825/3.125]

          1/4         1/8         1/16          1/32

Takže skončíte s číslem vyšším nebo nižším, než je zadané desetinné číslo. Vždy.

Proč na tom záleží? Zaokrouhlení.
Normální zaokrouhlení znamená 0,4 dolů, 5,9 nahoru. Takže to dělá záleží na tom, zda je výsledek Buď 0.049999999999.... nebo 0.0500000000... Možná víte, že to znamená 5 centů, ale počítač to neví a zaokrouhluje 0.4999 .. dolů (špatně) a 0.5000... nahoru (vpravo).
Vzhledem k tomu, že výsledek výpočtů s plovoucí desetinnou čárkou vždy obsahuje drobné chybové výrazy, je rozhodování čisté. To je beznadějné, pokud chcete desetinné kolo-to-dokonce zpracování s binárními čísly.

Nepřesvědčen? Trváte na tom, že ve vašem účtu je vše v pořádku?
Aktiva a pasiva se rovná? Ok, pak vezměte každé z uvedených formátovaných čísel každé položky, analyzujte je a spočítejte je s nezávislým desetinným systémem! Porovnejte to s formátovaným součtem.
Jejda, je něco špatně, že? 

Pro tento výpočet byla nutná extrémní přesnost a věrnost (použili jsme Oracle [.]. FLOAT), abychom mohli zaznamenat „miliardu penny“, která byla překonána.

Nepomůže proti této chybě. Protože všichni lidé automaticky předpokládají, že počítač je v pořádku, prakticky nikdo nekontroluje samostatně.

105
TSK
41
Nakilon

Nejprve byste si měli přečíst tento Co by měl každý počítačový vědec vědět o aritmetice s pohyblivou čárkou . Pak byste měli opravdu zvážit použití nějakého typu pevného bodu/libovolného čísla balíčku (např. Java BigNum, python desítkový modul), jinak budete ve světě zranění. Pak zjistěte, zda stačí použít nativní desetinný typ SQL. 

Floats/čtyřhry existují (ed) vystavit rychlý x87 fp, který je nyní do značné míry zastaralý. Nepoužívejte je, pokud vám záleží na přesnosti výpočtů a/nebo ne zcela kompenzujete jejich omezení.

22
Rich Schuler

Stejně jako další varování, SQL Server a .Net Framework použít jiný výchozí algoritmus pro zaokrouhlení. Ujistěte se, zda je zaškrtnuto parametr MidPointRounding v Math.Round (). .Net framework používá Bankersův algoritmus ve výchozím nastavení a SQL Server používá symetrické algoritmické zaokrouhlení. Podívejte se na článek Wikipedie zde

10
Darrel Miller

Zeptejte se svých účetních! Budou se na vás zamračit, abyste mohli používat float. Stejně jako některý z těch, které byly dříve publikovány, používejte float POUZE pokud se nestaráte o přesnost. I když bych byl vždy proti tomu, pokud jde o peníze.

V účetním software NENÍ přijatelný plovák. Použijte desetinné místo se 4 desetinnými místy.

7
Ricardo C

Plovoucí body mají nečekaná iracionální čísla.

Například nemůžete uložit 1/3 jako desetinné místo, bylo by to 0.3333333333 ... (a tak dále)

Plováky jsou vlastně uloženy jako binární hodnota a výkon 2 exponent.

Takže 1,5 je uloženo jako 3 x 2 na -1 (nebo 3/2)

Použití těchto exponentů base-2 vytváří některá lichá iracionální čísla, například:

Převést 1,1 na float a pak jej převést zpět, váš výsledek bude něco jako: 1.0999999999989

Důvodem je to, že binární reprezentace 1,1 je vlastně 154811237190861 x 2 ^ -47, více než dvojnásobné zvládnutí.

Více o tomto problému na můj blog , ale v podstatě, pro ukládání, jste lepší s desetinnými místy.

Na serveru Microsoft SQL máte datový typ money - to je obvykle nejlepší pro finanční ukládání. Je přesná na 4 desetinná místa.

Pro výpočty máte více problémů - nepřesnost je nepatrný zlomek, ale vložit ji do výkonové funkce a rychle se stává významnou. 

Desetinná místa však nejsou pro žádný druh matematiky příliš dobrá - například nativní podpora pro desetinné mocnosti neexistuje.

6
Keith

Trochu pozadí zde.

Žádný číselný systém nemůže přesně zpracovat všechna reálná čísla. Všechny mají svá omezení a to zahrnuje jak standardní IEEE plovoucí desetinnou čárku, tak desetinné desetinné místo. IEEE plovoucí desetinná čárka je přesnější na použitý bit, ale na tom nezáleží.

Finanční počty jsou založeny na staletích praxe papír-a-pero s přidruženými konvencemi. Jsou přiměřeně přesné, ale co je důležitější, jsou reprodukovatelné. Dva účetní pracující s různými čísly a sazbami by měli přijít se stejným číslem. Jakýkoli prostor pro nesrovnalosti je prostorem pro podvody.

Pro finanční výpočty je tedy správná odpověď cokoliv, co dává stejnou odpověď jako CPA, která je dobrá v aritmetice. Toto je desetinná aritmetika, ne IEEE plovoucí desetinná čárka.

5
David Thornley

Použijte decimal typ serveru SQL.

Nepoužívejte peníze nebo float.

peníze používají 4 desetinná místa, je rychlejší než použití desetinných míst , ALE trpí nějakými zřejmými a některými ne tak zjevnými problémy se zaokrouhlováním ( viz problém s připojením

5
Mitch Wheat

Co bych doporučil, je používat 64 bitová celá čísla, která ukládají celou věc v centech.

5
Joshua

Plováky nejsou přesné reprezentace, jsou možné problémy s přesností, například při přidávání velmi velkých a velmi malých hodnot. To je důvod, proč jsou pro měnu doporučovány desetinné typy, i když problém s přesností může být dostatečně vzácný.

Pro vyjasnění, desetinný typ 12,2 uloží těchto 14 číslic přesně, zatímco plovák nebude, protože používá binární reprezentaci interně. Například, 0.01 nemůže být reprezentován přesně plovoucí desetinnou čárkou - nejbližší reprezentace je vlastně 0.0099999998

4
Niall

Pro bankovní systém, kterému jsem pomohl rozvíjet, jsem byl zodpovědný za část systému "úrokové akruální". Každý den, můj kód počítal, jak velký zájem byl nashromážděný (earnt) na zůstatek ten den.

Pro tento výpočet byla požadována extrémní přesnost a věrnost (používali jsme FLOAT od Oracle), abychom mohli zaznamenat narůstající „miliardu penny“.

Když došlo k "kapitalizaci" úroku (tj. Zaplacení úroku zpět na váš účet), částka byla zaokrouhlena na cent. Typ dat pro zůstatky účtu byly dvě desetinná místa. (Ve skutečnosti to bylo složitější, protože se jednalo o multi-měnový systém, který mohl fungovat na mnoha desetinných místech - ale vždy jsme zaokrouhlili na "penny" této měny). Ano - tam, kde "zlomky" ztráty a zisku, ale když byly aktualizovány údaje o počítačích (peníze vyplacené nebo zaplacené) to byly vždy hodnoty REAL money.

To spokojilo účetní, auditory a testery.

Tak se poraďte se svými zákazníky. Řeknou vám svá bankovní/účetní pravidla a postupy.

4
Guy

Jediný důvod, proč použít Float za peníze, je, pokud se nestaráte o přesné odpovědi. 

4
David Singer

Další věc, kterou byste měli v účetních systémech znát, je, že nikdo by neměl mít přímý přístup k tabulkám. To znamená, že veškerý přístup do účetního systému musí probíhat prostřednictvím uložených procs. To zabrání podvodům nejen při útocích SQl. Interní uživatel, který chce spáchat podvod, by neměl mít možnost přímo měnit data v databázových tabulkách. Toto je kritická interní kontrola vašeho systému. Opravdu chcete, aby někteří nespokojení zaměstnanci chodili do backendu vaší databáze a začali je kontrolovat? Nebo skrýt, že schválili náklady neautorizovanému prodejci, když nemají schvalovací orgán? Pouze dva lidé ve vaší organizaci by měli mít přímý přístup k údajům ve vaší finanční databázi, vaší dba a jeho zálohování. Pokud máte mnoho dbas, měli by mít přístup pouze dva.

Zmiňuji to proto, že pokud vaši programátoři používali plovoucí v účetním systému, pravděpodobně nejsou zcela obeznámeni s myšlenkou vnitřních kontrol a nepovažovali je za své úsilí o programování.

3
HLGEM

Ještě lepší než používání desetinných míst je používat jen obyčejná stará celá čísla (nebo možná nějaký druh bigint). Tímto způsobem budete mít vždy nejvyšší možnou přesnost, ale lze zadat přesnost. Například číslo 100 by mohlo znamenat 1.00, které je formátováno takto:

int cents = num % 100;
int dollars = (num - cents) / 100;
printf("%d.%02d", dollars, cents);

Pokud chcete mít větší přesnost, můžete změnit 100 na větší hodnotu, například: 10 ^ n, kde n je počet desetinných míst.

3
Peter Stuifzand

Ze 100 frakcí n/100, kde n je přirozené číslo takové, že 0 <= n a n <100, pouze čtyři mohou být reprezentovány jako čísla s plovoucí řádovou čárkou. Podívejte se na výstup tohoto programu C:

#include <stdio.h>

int main()
{
    printf("Mapping 100 numbers between 0 and 1 ");
    printf("to their hexadecimal exponential form (HEF).\n");
    printf("Most of them do not equal their HEFs. That means ");
    printf("that their representations as floats ");
    printf("differ from their actual values.\n");
    double f = 0.01;
    int i;
    for (i = 0; i < 100; i++) {
        printf("%1.2f -> %a\n",f*i,f*i);
    }
    printf("Printing 128 'float-compatible' numbers ");
    printf("together with their HEFs for comparison.\n");
    f = 0x1p-7; // ==0.0071825
    for (i = 0; i < 0x80; i++) {
        printf("%1.7f -> %a\n",f*i,f*i);
    }
    return 0;
}
2
Lars Bohl

Vždy můžete psát něco jako typ Money pro .Net.

Podívejte se na tento článek: Typ peněz pro CLR - Autor podle mého názoru udělal vynikající práci.

2
Tomer Pintel

Používal jsem peníze typu SQL pro ukládání peněžních hodnot. Nedávno jsem musel pracovat s řadou online platebních systémů a všiml jsem si, že někteří z nich používají celá čísla pro ukládání peněžních hodnot. V mých současných a nových projektech jsem začal používat celá čísla a jsem docela spokojen s tímto řešením.

2
George

Pravděpodobně budete chtít použít nějakou formu reprezentace pevných bodů pro měnové hodnoty. Budete také chtít prozkoumat Bankerovo zaokrouhlování (také známé jako "kulatá polovina i"). Zabraňuje se zkreslení, které existuje v obvyklé "kulaté polovině" metody.

1
user6931

Uvažovali jste o použití typu dat peněz pro ukládání dolarových částek?

Pokud jde o Con, že desetinné místo zabere o jeden byte, řekl bych, že se o to nestarám. V 1 milionu řádků budete používat pouze 1 MB a úložiště je v těchto dnech velmi levné.

1
Espo

Bez ohledu na to, co děláte, musíte být opatrní při zaokrouhlování chyb. Vypočítejte pomocí většího stupně přesnosti, než se zobrazí.

1
1800 INFORMATION

Vaši účetní budou chtít kontrolovat, jak budete kolo. Použití float znamená, že budete neustále zaokrouhlovat, obvykle pomocí příkazu typu FORMAT (), což není způsob, jakým to chcete udělat (místo toho použijte podlahu/strop).

Máte měnové datové typy (peníze, malé peníze), které by měly být použity namísto float nebo real. Ukládání desetinných míst (12,2) odstraní vaše zaokrouhlení, ale také je odstraní během mezilehlých kroků - což ve finanční aplikaci opravdu vůbec není to, co chcete.

0
David T. Macknet

Jedná se o vynikající článek popisující kdy použít plovoucí a desetinné čárky . Float ukládá přibližnou hodnotu a desetinná místa s přesnou hodnotou.

Stručně řečeno, přesné hodnoty jako peníze by měly používat desetinné číslo a přibližné hodnoty jako vědecká měření by měly používat plovák. 

Zde je zajímavý příklad, který ukazuje, že jak plovoucí, tak desetinná místa mohou ztrácet přesnost. Když přidáváte číslo, které není celé číslo, a odečte se od toho, že stejný počet plováků má za následek ztrátu přesnosti při desetinné čárce:

    DECLARE @Float1 float, @Float2 float, @Float3 float, @Float4 float; 
    SET @Float1 = 54; 
    SET @Float2 = 3.1; 
    SET @Float3 = 0 + @Float1 + @Float2; 
    SELECT @Float3 - @Float1 - @Float2 AS "Should be 0";

Should be 0 
---------------------- 
1.13797860024079E-15

Při násobení celého čísla a dělení stejným číslem, desetinná místa ztrácejí přesnost, zatímco plováky ne.

DECLARE @Fixed1 decimal(8,4), @Fixed2 decimal(8,4), @Fixed3 decimal(8,4); 
SET @Fixed1 = 54; 
SET @Fixed2 = 0.03; 
SET @Fixed3 = 1 * @Fixed1 / @Fixed2; 
SELECT @Fixed3 / @Fixed1 * @Fixed2 AS "Should be 1";

Should be 1 
--------------------------------------- 
0.99999999999999900
0
BrokeMyLegBiking

Vždy používejte desetinné místo. Float vám poskytne nepřesné hodnoty kvůli problémům se zaokrouhlováním.

0
Roel Vlemmings

Čísla plovoucí bodu mohou pouze reprezentovat čísla, která jsou součtem záporných násobků základny - pro binární plovoucí desetinnou čárku, to jsou samozřejmě dvě.

Existují pouze čtyři desetinné zlomky reprezentovatelné přesně v binární plovoucí desetinné čárce: 0, 0,25, 0,5 a 0,75. Všechno ostatní je aproximací, stejně jako 0.3333 ... je aproximací 1/3 v desetinné aritmetice.

Plovoucí bod je dobrou volbou pro výpočty, kde je důležitý rozsah výsledku. Je to špatná volba, kde se snažíte být přesný na určitý počet desetinných míst.

0
Mike Dimmick