Vím, že aritmetika s plovoucí desetinnou čárkou má problémy s přesností. Obvykle je překonávám přechodem na pevné desetinné číslo, nebo jednoduše zanedbáním chyby.

Nevím však, jaké jsou příčiny této nepřesnosti. Proč existuje tolik problémů se zaokrouhlováním čísel float?

Komentáře

  • Abych byl přesný, je to ‚ div Ve skutečnosti nejde o chybu způsobenou zaokrouhlováním, které si většina lidí dělá starosti – ‚ s tím, že binární zaokrouhlování s plovoucí desetinnou čárkou se chová neintuitivně. Přepnutí na desetinnou reprezentaci může způsobit, že se zaokrouhlování bude chovat intuitivnějším způsobem, ale výměnou téměř vždy zvýšíte relativní chybu (nebo musíte kompenzovat zvětšením úložného prostoru).
  • Můj pokus o objasnění nejběžnějších zmatků: floating-point-gui.de
  • myslím, co znamená @DanielPryden is “ Přepnutím na reprezentaci [pevný bod] se může zaoblení chovat intuitivněji … “ . co způsobuje problémy se zaokrouhlováním, ať už je to ‚ s čísly s pevnou nebo plovoucí desetinnou čárkou konečná šířka slova. ‚ je to jen to, že s plovoucí desetinnou čárkou velikost chyby zaokrouhlování obvykle zůstává zhruba úměrná velikosti zaokrouhlovaného čísla. (kromě případů, kdy jste opravdu malí a “ denormalizovaná “ čísla.)
  • @robert: To ‚ není přesně to, na co jsem měl na mysli. Chyba “ „, se kterou se většina lidí setkává s pohyblivou řádovou čárkou, nemá ‚ nic společného s s plovoucí desetinnou čárkou jako takovou, je ‚ základem. Plovoucí a zdvojnásobení IEEE-754 používá exponent v základně 2, což znamená, že zlomková čísla se zaokrouhlují na záporné síly dvou (1/2, 1/16, 1/1024 atd.), Spíše než na záporné síly 10 (1 / 10, 1/1000 atd.) To vede k neintuitivním výsledkům, jako je 0,1 zaokrouhlování na 0,1000001 a podobné problémy.
  • Čísla s plovoucí desetinnou čárkou můžete provádět v základu 10 – ‚ s jak funguje .NET ‚ s decimal typ. Pevný bod je na druhé straně jiný. Pokud je váš dosah omezený, pevný bod je skvělá odpověď. Díky omezujícímu rozsahu je však pevný bod nevhodný pro mnoho matematických aplikací a implementace čísel s pevným bodem často nejsou v hardwaru dobře optimalizovány.

Odpovědět

Je to proto, že některé zlomky potřebují vyjádřit velmi velké (nebo dokonce nekonečné) množství míst bez zaokrouhlování. To platí pro desetinnou notaci stejně jako pro binární nebo jakoukoli jinou. Pokud byste omezili počet desetinných míst, které se mají použít pro vaše výpočty (a vyhněte se provádění výpočtů ve zlomkové notaci), museli byste zaokrouhlit i jednoduchý výraz jako 1/3 + 1/3. Místo toho, abyste ve výsledku psali 2/3, byste museli napsat 0,3333 + 0,33333 = 0,66666, což není totožné s 2/3.

V případě počítače je počet číslic omezen technickou podstatou svých registrů paměti a CPU. Interně použitá binární notace přidává další obtíže. Počítače obvykle nemohou „vyjadřovat čísla ve zlomkové notaci, ačkoli některé programovací jazyky tuto schopnost přidávají, což umožňuje do určité míry se těmto problémům vyhnout.

Co by měl každý počítačový vědec vědět o aritmetice s plovoucí desetinnou čárkou

Komentáře

  • Spot on. Ale také bych si všiml, že některá čísla, která končit v desítkové soustavě ‚ t končit v binární podobě. Zejména 0,1 je opakující se číslo v binární podobě, takže žádné binární číslo s plovoucí desetinnou čárkou nemůže přesně představovat 0,1.
  • Plovoucí body nejsou ‚ užitečné pouze pro mnoho desetinných míst. 32bitová celá čísla mohou počítat až asi 4 miliardy, ale 32bitový float může být téměř nekonečně velký.
  • Zlomky, které můžeme vyjádřit jako konečná desetinná místa, jsou zejména ty, jejichž jmenovatelé ‚ primární faktorizace obsahuje pouze 2 a 5 (např. můžeme vyjádřit 3/10 a 7/25 , ale ne 11/18). Když přejdeme na binární, ztratíme faktor 5, takže lze přesně vyjádřit pouze dyadické racionály (např. 1/4, 3/128).

Odpověď

Zaokrouhlovací chyby vycházejí především ze skutečnosti, že nekonečno všech reálných čísel nemůže být reprezentován konečnou pamětí počítače , natož malý kousek paměti, jako je jedna proměnná s plovoucí desetinnou čárkou , takže mnoho uložených čísel je jen přibližné hodnoty čísla, které mají představovat.

Protože existuje pouze omezený počet hodnot, které nejsou aproximace a každá operace mezi aproximací a jiným číslem vede k aproximaci, chyby zaokrouhlování jsou téměř nevyhnutelné .

Důležité je uvědomit si, kdy je pravděpodobné, že způsobí problém a podniknout kroky ke zmírnění rizik .


Kromě David Goldberg je základní co každý počítačový vědec Měli byste vědět o aritmetice s plovoucí desetinnou čárkou (znovu publikováno společností Sun / Oracle jako příloha k jejich Numerickému Průvodce výpočty ), o kterém se zmínil thorsten , ACCU deník přetížení publikoval vynikající sérii článků od Richarda Harrisa o Floating Point Blues .

Série začala

Numerical co mputing má mnoho úskalí. Richard Harris začíná hledat stříbrnou kulku.

Drak numerické chyby není často probuzen z jeho spánku, ale bude-li k němu přistupován obezřetně, způsobí neopatrným programátorským výpočtům občas katastrofické škody.

Tolik, že někteří programátoři, kteří na něj narazili v lesích aritmetiky s plovoucí desetinnou čárkou IEEE 754, doporučují svým kolegům, aby necestovali po této férové zemi.

V této sérii článků prozkoumáme svět numerických výpočtů, kontrastní aritmetika s plovoucí desetinnou čárkou s některými technikami, které byly navrženy jako bezpečnější náhrady. Dozvíme se, že území draka je opravdu dalekosáhlé a že obecně musíme opatrně šlapat, pokud se bojíme jeho zničující pozornost.

Richard začíná vysvětlením taxonomie reálných čísel, racionálních, iracionálních, algebraických a transcendentálních. Poté pokračuje vysvětlením reprezentace IEEE754, než přejde k chybě zrušení a pořadí problémů s prováděním.

Pokud nečtete hlouběji než toto, budete mít vynikající základy v problémech spojených s čísly s plovoucí desetinnou čárkou .

Pokud se však chcete dozvědět více, pokračuje s

Poté přepne na pokus o pomoc s léčením Calculus Blues

a v neposlední řadě existuje

Celá řada článků je stojí za to se na ně podívat a celkem na 66 stránkách jsou stále menší než 77 stránek Goldbergovy práce .

I když to Série pokrývá většinu stejného terénu, shledal jsem ji spíše přístupnější než Goldbergův papír . Zjistil jsem také, že je snazší porozumět složitějším částem článku po přečtení dřívějších článků o Richardsovi a po těchto raných článcích se Richard rozvětvuje do mnoha zajímavých oblastí, kterých se Goldbergova práce nedotkla.

As takto hovoří ak zmíněno v komentářích:

Jako autor ty články, které bych rád zmínil, že jsem vytvořil jejich interaktivní verze na svém blogu www.thusspakeak.com počínaje protospakeak.com/ak/2013/06 .

Komentáře

  • Jako autor těchto článků bych rád ‚ zmínil, že jsem na svém blogu www.thusspakeak.com vytvořil jejich interaktivní verze počínaje protospakeak.com/ak/2013/06 .
  • děkuji @ protospakea.k. Přidal jsem ‚ poznámku na mou odpověď, a tho interaktivní prvky fungují velmi dobře.

Odpověď

No, thorsten má definitivní odkaz . Přidal bych:

Jakákoli forma reprezentace bude mít u nějakého čísla nějakou chybu zaokrouhlování. Zkuste vyjádřit 1/3 v IEEE s plovoucí desetinnou čárkou nebo v desítkové soustavě. Ani jeden to nedokáže přesně. To jde nad rámec odpovědi na vaši otázku, ale úspěšně jsem použil toto pravidlo:

  • Ukládejte uživatelem zadané hodnoty v desítkové soustavě (protože je téměř jistě zadali v desítkové reprezentaci – velmi málo uživatelů použije binární nebo hex). Tímto způsobem máte vždy přesnou reprezentaci zadanou uživatelem.
  • Pokud musíte ukládat zlomky zadané uživatelem, ukládejte čitatele a jmenovatele (také v desítkové soustavě)
  • Pokud máte systém s více měrnými jednotkami pro stejné množství (jako Celsius / Fahrenheit) a uživatel může zadat obojí, uložit hodnotu, kterou zadal, a jednotky, do kterých je zadal. Nepokoušejte se převést a uložit jako jednu reprezentaci, pokud to nezvládnete bez ztráty přesnosti / přesnosti. U všech výpočtů použijte jednotky a uložené hodnoty.
  • Ukládejte strojem generované hodnoty do plovoucí desetinné čárky IEEE (mohou to být čísla generovaná elektronickým měřicím zařízením, jako je analogový snímač s A / D převodníkem, nebo nezaokrouhlený výsledek výpočtu). Všimněte si, že to neplatí, pokud čtete snímač přes sériové připojení a již to dává hodnotu v desítkovém formátu (např. 18,2 ° C).
  • Ukládejte součty, které lze zobrazit, atd., v desítkovém formátu (jako bankovní účet) Zůstatek). Vhodně zaokrouhlete, ale tuto hodnotu použijte jako definitivní hodnotu pro všechny budoucí výpočty.

Komentáře

  • Chtěl bych přidat: Zvažte použití matematický balíček s libovolnou přesností, jako je ARPREC nebo decNumber.
  • Nemám ‚ t desítkové číslo (na rozdíl od binárního) má mnoho výhod pro celočíselné hodnoty, jako je čitatel a jmenovatel zlomku. Buď můžete uložit přesné celočíselné hodnoty, a binární je efektivnější. ‚ jsou určité náklady na převod tam a zpět pro vstup a výstup, ale ‚ je pravděpodobné, že budou zaplaveny náklady na fyzickou provádění I / O.

Odpověď

Zdá se, že dosud nebyly zmíněny koncepty nestabilního algoritmu a špatně podmíněný problém . Nejprve se budu zabývat tím prvním, protože to se zdá být častějším úskalím pro začínající numeriky.

Zvažte výpočet pravomocí (vzájemného) zlatého řezu φ=0.61803…; jedním z možných způsobů, jak toho dosáhnout, je použít vzorec rekurze φ^n=φ^(n-2)-φ^(n-1) počínaje φ^0=1 a φ^1=φ. Pokud spustíte tuto rekurzi ve svém oblíbeném výpočetním prostředí a porovnáte výsledky s přesně vyhodnocenými schopnostmi, zjistíte pomalou erozi významných čísel. Tady je to, co se stane například v Mathematica :

ph = N[1/GoldenRatio]; Nest[Append[#1, #1[[-2]] - #1[[-1]]] & , {1, ph}, 50] - ph^Range[0, 51] {0., 0., 1.1102230246251565*^-16, -5.551115123125783*^-17, 2.220446049250313*^-16, -2.3592239273284576*^-16, 4.85722573273506*^-16, -7.147060721024445*^-16, 1.2073675392798577*^-15, -1.916869440954372*^-15, 3.1259717037102064*^-15, -5.0411064211886014*^-15, 8.16837916750579*^-15, -1.3209051907825398*^-14, 2.1377864756200182*^-14, -3.458669982359108*^-14, 5.596472721011714*^-14, -9.055131861349097*^-14, 1.465160458236081*^-13, -2.370673237795176*^-13, 3.835834102607072*^-13, -6.206507137114341*^-13, 1.004234127360273*^-12, -1.6248848342954435*^-12, 2.6291189633497825*^-12, -4.254003796798193*^-12, 6.883122762265558*^-12, -1.1137126558640235*^-11, 1.8020249321541067*^-11, -2.9157375879969544*^-11, 4.717762520172237*^-11, -7.633500108148015*^-11, 1.23512626283229*^-10, -1.9984762736468268*^-10, 3.233602536479646*^-10, -5.232078810126407*^-10, 8.465681346606119*^-10, -1.3697760156732426*^-9, 2.216344150333856*^-9, -3.5861201660070964*^-9, 5.802464316340953*^-9, -9.388584482348049*^-9, 1.5191048798689004*^-8, -2.457963328103705*^-8, 3.9770682079726053*^-8, -6.43503153607631*^-8, 1.0412099744048916*^-7, -1.6847131280125227*^-7, 2.725923102417414*^-7, -4.4106362304299367*^-7, 7.136559332847351*^-7, -1.1547195563277288*^-6} 

Údajný výsledek pro φ^41 má nesprávné znaménko a ještě dříve vypočítané a skutečné hodnoty pro φ^39 nesdílejí žádné společné číslice (3.484899258054952 * ^ – 9 for the computed version against the true value 7.071019424062048 *^-9). Algoritmus je tedy nestabilní a tento rekurzní vzorec by se neměl používat v nepřesné aritmetice. Je to kvůli inherentní povaha rekurzního vzorce: existuje „rozpadající se“ a „rostoucí“ řešení této rekurze a pokus o výpočet „rozpadajícího se“ řešení pomocí dopředného řešení, když existuje alternativní „rostoucí“ řešení, prosí o numerický zármutek. Měli bychom tedy zajistit, aby jeho numerické algoritmy byly stabilní.

Nyní k konceptu špatně podmíněného problému: i když může existovat stabilní způsob, jak to udělat něco číselně, může se velmi dobře stát, že problém, který máte Váš algoritmus prostě nemůže být vyřešen. To je chyba samotného problému, a ne metody řešení. Kanonickým příkladem v numerice je řešení lineárních rovnic zahrnujících tzv. „Hilbertovu matici“:

Hilbertova matice

matice je kanonickým příkladem špatně podmíněné matice: pokus o řešení systému s velkou Hilbertovou maticí může vrátit nepřesné řešení.

Zde „sa Mathematica demonstrace: porovnejte výsledky přesné aritmetiky

Table[LinearSolve[HilbertMatrix[n], HilbertMatrix[n].ConstantArray[1, n]], {n, 2, 12}] {{1, 1}, {1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}} 

a nepřesné aritmetiky

Table[LinearSolve[N[HilbertMatrix[n]], N[HilbertMatrix[n].ConstantArray[1, n]]], {n, 2, 12}] {{1., 1.}, {1., 1., 1.}, {1., 1., 1., 1.}, {1., 1., 1., 1., 1.}, {1., 1., 1., 1., 1., 1.}, {1., 1., 1., 1., 1., 1., 1.}, {1., 1., 1., 1., 1., 1., 1., 1.}, {1., 1., 1., 1., 1., 1., 1., 1., 1.}, {1., 1., 1., 0.99997, 1.00014, 0.999618, 1.00062, 0.9994, 1.00031, 0.999931}, {1., 1., 0.999995, 1.00006, 0.999658, 1.00122, 0.997327, 1.00367, 0.996932, 1.00143, 0.999717}, {1., 1., 0.999986, 1.00022, 0.998241, 1.00831, 0.975462, 1.0466, 0.94311, 1.04312, 0.981529, 1.00342}} 

(Pokud jste to vyzkoušeli v Mathematica , všimnete si několika chybových zpráv varujících před zobrazením špatného stavu.)

V obou případech jednoduše zvětšíte přesnost není lékem; jen to oddálí nevyhnutelnou erozi čísel.

S tím byste se mohli setkat. Řešení mohou být obtížná: zaprvé, buď se vrátíte na rýsovací prkno, nebo se budete procházet deníky / knihami / čímkoli, abyste zjistili, zda někdo jiný přišel s lepším řešením, než máte vy; za druhé se buď vzdáte, nebo přeformulujete svůj problém na něco přitažlivějšího.


Nechám vás s citátem od Dianne O „Leary:

Život nás může potkat s některými špatně podmíněnými problémy, ale není dobrý důvod spokojit se s nestabilním algoritmem.

Odpověď

protože základ 10 desetinných čísel nelze vyjádřit v základu 2

nebo jinými slovy 1/10 nelze transformována na zlomek se silou 2 ve jmenovateli (což jsou v podstatě čísla s plovoucí desetinnou čárkou)

Komentáře

  • Není to úplně pravda: 0,5 a 0,25 lze vyjádřit v základně 2. Myslím, že máte na mysli “ ne všechna desetinná čísla základny 10 „.
  • Přesněji. Ne všechna zlomková čísla lze přesně vyjádřit pomocí zápisu s plovoucí desetinnou čárkou (tj. S. Jak základna 2, tak základna 10 mají tento přesný problém). Zkuste 9*3.3333333 v desítkové soustavě a srovnejte jej s 9*3 1/3
  • Toto je nejběžnější zdroj s plovoucí desetinnou čárkou zmatek. .1 + .1 != .2 protože se používá binární kódování s plovoucí desetinnou čárkou, nikoli desítkové.
  • @SeanMcMillan: A 1.0/3.0*3.0 != 1.0, protože plovoucí -bodové binární kódování se používá, nikoli trinární.

Odpověď

V matematice je nekonečně mnoho racionálních čísel . 32bitová proměnná může mít pouze 2 32 různé hodnoty a 64bitová proměnná pouze 2 64 hodnoty. Proto existuje nekonečně mnoho racionálních čísel, která nemají přesné zastoupení.

Mohli bychom přijít se schématy, která by nám umožnila dokonale reprezentovat 1/3 nebo 1/100. Ukazuje se, že z mnoha praktických důvodů to není velmi užitečné. Existuje jedna velká výjimka: ve financích se často objevují desetinné zlomky. Je tomu tak hlavně proto, že finance jsou v zásadě lidská činnost, nikoli fyzická.

Proto se obvykle rozhodneme použít binární plovoucí desetinnou čárku a zaokrouhlit libovolnou hodnotu, která nemůže být v binárním vyjádření. Ale ve financích někdy volíme desetinnou plovoucí desetinnou čárku a zaokrouhlujeme hodnoty na nejbližší desetinnou hodnotu .

Komentáře

  • Ještě horší je, že zatímco nekonečné (spočetně nekonečné) množství paměti by člověku umožnilo reprezentovat všechny racionály, nebylo by postačující pro reprezentaci realit. Ještě horší je, že téměř všechna reálná čísla nejsou vypočítatelná čísla. Nejlepší, co můžeme udělat s konečným množstvím paměti, je přiblížit podmnožinu konečných rozsahů real.
  • @Kevin: ‚ Mluvíte o vypočítatelných číslech, což je malá podmnožina realit. (Podmnožina s mírou nula).
  • +1 pro nejzákladnější vysvětlení: ‚ Snažíte se představovat nekonečné množství čísel s konečným počtem bitů.
  • @DavidHammen: Vyčíslitelná čísla jsou malou podmnožinou ( nula) realit – ale každé číslo, se kterým ‚ kdy v programu budete pracovat, je podle definice vypočítatelné.
  • @Giorgio: If vyberete správné znázornění, druhá odmocnina 2 je reprezentovatelná, například jako řetězec "√2". (Moje stará kalkulačka HP-48 to dokázala přesně a kvadratura této hodnoty vedla k přesně 2.0.) Pro libovolné existuje pouze spočetné nekonečno reprezentovatelných reálných čísel konečná reprezentace – ale žádný výpočet nemůže přinést číslo, které není v zásadě reprezentovatelné. V praxi binární plovoucí desetinná čárka drasticky omezuje množinu reprezentovatelných čísel, s výhodou bleskové rychlosti a malého úložiště ve srovnání se symbolickými reprezentacemi.

Odpovědět

jediný skutečně zjevný „problém zaokrouhlování“ s čísly s plovoucí desetinnou čárkou, o kterém si myslím, je s filtry klouzavého průměru:

$$ \ begin {align} y [n] & = \ frac {1} {N} \ sum \ limits_ {i = 0} ^ {N-1} x [ni] \ & = y [n-1] + \ frac {1} {N} (x [n] – x [nN]) \ \ end {align} $$

aby to fungovalo bez hromadění hluku, chcete se ujistit, že $ x [n] $, které přidáte do aktuálních vzorků, je přesně stejné jako $ x [nN] $, které odečtete $ N $ vzorky do budoucnosti. pokud tomu tak není, pak se liší trochu hovno, které se zasekne ve vaší zpožďovací linii a nikdy nevyjde. to je proto, že tento filtr s klouzavým průměrem je ve skutečnosti vytvořen s IIR, který má okrajově stabilní pól na $ z = 1 $ a nulu, která jej ruší uvnitř. ale je to integrátor a všechny kecy, které se integrují a nebudou zcela odstraněny, budou v integračním součtu navždy existovat. to je místo, kde pevný bod nemá stejný problém jako čísla s plovoucí desetinnou čárkou.

Komentáře

  • hej, ‚ t $ LaTeX $ math markup nefunguje ve fóru prog.SE ??? that ‚ s opravdu chromý, pokud to není ‚ t.
  • Viz to na meta.SO a související otázky

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *