V dobách, kdy cpu neměly dostatek výkonu, přišel Intel s IEEE 754, kde za cenu nižší přesnosti se dala čísla rychle počítat.
Tohle mě zarazilo - myslel jsem, že IEEE 754 je „nejpřesnější co se do takhle velkého typu (32/64bit) vejde“ - zejména že operace jsou „exaktní“ právě včetně korektního zaokrouhlení (kvůli tomu se tam občas používají ty intermediate 80bit hodnoty). Existuje něco, co by bylo přesnější, a problémem je pomalé počítání? Jak to funguje?
Ne nejpřesnější, ale efektivně využití prostoru. Čím čísla mají méně číslic, tím je hustota vyšší a tím i přesnost. Je jedno kolik bitů si necháš na číslo, pořád platí, že máš radix 2 a veškerá čísla za desetinným rozvojem musíš vyjádřit v základu jako 2^x * m, tady vzniká ta nepřenost, počet bitů jí jen posouvá "dozadu". U krátkých čísel to je jedno, k zaukrouhlení proběhne třeba až na 20. místě za desetinnou čárkou, takže ve výsledku pořád 0.1 + 0.2 bude 0.3. Ale u těch dlouhých čísel skáčet hodně vedle, stejně jako u těch příliš malých.
Pokud to chceš přesně, je tady Decimal Floating Point aka EEE754-2008. Intel má třeba svoje rozšíření Intel DFP Math (dříve Intel BCD opcodes), IBM má decNumber (tady je pěkná knihovna
https://github.com/libdfp/libdfp, kterou jsme dříve používali u našeho telco operátora), GCC má také zabudovanou podporu (
https://gcc.gnu.org/onlinedocs/gcc/Decimal-Float.html).
Zpomalení výpočtů se pohybuje od 2x až i po 50x podle typu operací, přes SIMD/AVX se dá ztráta dohnat. Jako reference může posloužit starší článek
http://iccd.et.tudelft.nl/2009/proceedings/465Anderson.pdf, který pořád mám v záložkách. Samozřejmě, nesmím zapomenout na úžasné články Pavla Tišnovského tady na rootu,
https://www.root.cz/clanky/interni-reprezentace-numerickych-hodnot-od-skutecneho-pocitacoveho-praveku-po-ieee-754-2008/ a
https://www.root.cz/clanky/interni-reprezentace-numerickych-hodnot-od-skutecneho-pocitacoveho-praveku-po-ieee-754-2008-dokonceni/Pokud jde o samotné zaokrouhlování, existují 4 možnosti, round nearest, round towards positive, round towards negative, round towards zero, tak praví IEEE 754. Každý jazyk si pak vybral ten vhodnější způsob podle toho, co se v něm za programy dělají a jaký na to autoři měli názor. Některé jazyky dovedou dokonce ti dát vybrat, např. v CUDA si mohu zvolit co chci před samotným výpočtem.
To je příšerná reprezentace dat… Zda můžete použít float závisí na tom, jaký tam může být rozsah hodnot. Může být tak malý, že se vše vejde správně do float. Osobně bych ale v tomhle případě použil Decimal (nebo ekvivalent). V databázi to stejně nejspíš bude také reprezentované jako Number (tj. celkový počet platných míst a počet míst za desetinnou čárkou), takže konvertovat to na float je zbytečné. Navíc s tím neprovádíte žádné složité výpočty, takže pomalost Decimalu ničemu nevadí. Naopak máte jistotu, že nemusíte řešit záludnosti floatu.
Jak jsem psal výše, přesnost nezávisí na velikosti čísla, ale spíše na jeho schopnosti se bezezbytku vyjádřit jako 2^x * m. Decimal je správná volba pro ukládání čísel, kde musím zachovat přesnost, ale také zabítá v databázích více místa, např. takový DECIMAL(20,6) v mysql zabere 13 bajtů, v Oraclu trochu méně, ale princip je podobný. Souhlas, že decimal by před float měl mít přednost kdykoliv si nejsem jistý, že mi float nevadí.