Python zaokruhlovanie na cele cislo nefunguje spravne

Re:Python zaokruhlovanie na cele cislo nefunguje spravne
« Odpověď #30 kdy: 21. 02. 2021, 13:31:20 »
Aha, sakra, vzdyt on ten C# taky zaokrouhluje na nejblizsi sude cislo...

Citace
Round(Double)   
Zaokrouhlí hodnotu s plovoucí desetinnou čárkou s dvojitou přesností na nejbližší celočíselnou hodnotu a zaokrouhlí střední hodnoty na nejbližší sudé číslo.

Ach jo. Raketaci zase mizi ze sceny. Jdu pryc z tohoto topicu. Ale ja se zase vratim.

Ale stejne si neodpustim rypnout. C# zase ukazal, ze knihovnu ma udelanou nejlip ze vsech a nejjasneji ze vsech. Kdyby to tak mela i Java nebo Python, neni zde dneska zadneho takovehoto sporu.

https://docs.microsoft.com/cs-cz/dotnet/api/system.math.round?view=net-5.0#System_Math_Round_System_Double_
« Poslední změna: 21. 02. 2021, 13:34:05 od registrovany123 »


Mlocik97

  • *****
  • 830
  • Ubunťák, JS dev.
    • Zobrazit profil
    • E-mail
Re:Python zaokruhlovanie na cele cislo nefunguje spravne
« Odpověď #31 kdy: 21. 02. 2021, 13:57:25 »
Pokud nechci at se mi posunuje vysledek jednim smerem pri vypoctech, tak sakra himl hergot fix NEZAOKROUHLUJU!!! Pocitam s floaty tak jak vysly!
A to snad není zaokrouhlování? Float má pevně dlouhou mantissu, a výsledky běžně počítaných funkcí (i třeba pouhé sčítání čísel když to zrovna náhodou nevyjde „hezky“) se musí zaokrouhlit, aby šly reprezentovat.

To je ako argument že by sme teraz mali používať namiesto pí číslo 3, lebo aj tak presnú hodnotu čísla pí nevieme ani prezentovať ani nevieme použiť pri výpočte 100% presnú hodnotu pí (čož by vyžadovalo nekonečno času, keďže je to iracionálne číslo s nekonečným počtom cifier) Takže ok, od dnes používam namiesto pí, jednoducho číslo 3. Nemali by sme sa snažiť o najväčšiu presnosť, a až keď už vyššia není možná (kvôli prostriedkom) tak až potom zavádzať nepresnosť, ale na čo pridávať nepresnosť keď to není potrebné?

Takže v tomto plne súhlasím s Jenda.
« Poslední změna: 21. 02. 2021, 14:01:51 od Mlocik97 »

_Jenda

  • *****
  • 1 550
    • Zobrazit profil
    • https://jenda.hrach.eu/
    • E-mail
Re:Python zaokruhlovanie na cele cislo nefunguje spravne
« Odpověď #32 kdy: 21. 02. 2021, 14:25:12 »
Pokud nechci at se mi posunuje vysledek jednim smerem pri vypoctech, tak sakra himl hergot fix NEZAOKROUHLUJU!!! Pocitam s floaty tak jak vysly!
A to snad není zaokrouhlování? Float má pevně dlouhou mantissu, a výsledky běžně počítaných funkcí (i třeba pouhé sčítání čísel když to zrovna náhodou nevyjde „hezky“) se musí zaokrouhlit, aby šly reprezentovat.

Vsak jo, ale at se zaokrouhli, az kdyz se jdou reprezentovat, a ne v procesu vypoctu.
Zakrouhlování i v procesu výpočtu je nevyhnutelné (pokud nepoužíváte speciální "exact" matematiku, která je ale nesmyslně náročná a předpokládám že v ní některé věci ani vyjádřit nepůjdou). Nebo jestli vás chápu: chtěl byste jedno zaokrouhlování při interním počítání na počítači (které bude round to even nebo obdobné, co nevnáší systematickou chybu) a druhé zaokrouhlování pro zobrazování člověku?

Citace
A mozna i v 6 tride jsem si vsiml, ze Excel vzdycky zaokrouhluje zobrazovane hodnoty (5 zaokrhluje nahoru), ale pocita se skutecnyma hodnotama.
To není pravda, dokonce jsem kvůli vám nastartoval virtuál s widlema a Office 2007.
Kód: [Vybrat]
B2 = 1E+21
C2 = 1
D2 = B2+C2
E2 = D2-B2 # zobrazí 0, mělo by zobrazit 1. Pokud nastavíme B2=1E+11, tak to správně zobrazí 1

Mam ceni vyrobku v excelu. Tento cenik budu jistojiste mit s presnosti na 1 desetinne misto (desitky haleru). Kdyz budu chtit zvysit ceny o inflaci, tak je zvednu o inflaci, nacez 2. desetinne misto zaokrouhlim klasickou metodou:

10.50,- CZK -> + 3% inflace -> 10.815,- CKZ -> 10.8 CZK

Ukazte mi, v cem je podle vas problem se zaokrohlovanim.
Vždyť už to tady psalo několik lidí: systematická chyba, zdražíte dohromady o víc než inflace. (jenom upozorňuji, že u příkladu s cenami to asi není nějak zásadní, ale tipuji že nějaké dlouho trvající numerické výpočty už s tím problém mají).

Jose D

  • *****
  • 850
    • Zobrazit profil
Re:Python zaokruhlovanie na cele cislo nefunguje spravne
« Odpověď #33 kdy: 21. 02. 2021, 14:26:58 »
když už se nám tady rozjel offtopic.

To je ako argument že by sme teraz mali používať namiesto pí číslo 3, lebo aj tak presnú hodnotu čísla pí nevieme ani prezentovať ani nevieme použiť pri výpočte 100% presnú hodnotu pí (

a není to tak, že IRL přesně tohle děláme? Rozhodneš se o požadovaný přesnosti, a místo π použiješ nějakou dostatečně přesnou aproximaci?

Mlocik97

  • *****
  • 830
  • Ubunťák, JS dev.
    • Zobrazit profil
    • E-mail
Re:Python zaokruhlovanie na cele cislo nefunguje spravne
« Odpověď #34 kdy: 21. 02. 2021, 14:43:19 »
když už se nám tady rozjel offtopic.

To je ako argument že by sme teraz mali používať namiesto pí číslo 3, lebo aj tak presnú hodnotu čísla pí nevieme ani prezentovať ani nevieme použiť pri výpočte 100% presnú hodnotu pí (

a není to tak, že IRL přesně tohle děláme? Rozhodneš se o požadovaný přesnosti, a místo π použiješ nějakou dostatečně přesnou aproximaci?

Áno keď presnosť nepotrebuješ, ale Filip sem dával príklad z banky, tam si myslím že presnosť naopak je potrebná, a navyše ak není tak to je ešte dôvod k tomu prečo tá funkcia v Pythone je nezmyselná (resp. určite sa má výhodu v určitých použitiach, ale štandardný round() mali nechať klasické základoškolské zaokruhlovanie. A ono príklad IRL ako človek vs počítač je tiež miešanie jabĺk s hruškami. Pretože ľudský mozog funguje inak ako počítač. Zatiaľ čo počítač má pamäť takú že raz mu dáš informáciu a on si ju pamätá, tak mozog nikoliv a mozog proste zabúda, najmä komplexnejšie informácie, preto sa zjednodušujú aby si to mozog zapamätal jednoduchšie. Ale keď do kalkulačky zadáš pí * 3 tak ti to nedá výsledok 9.
« Poslední změna: 21. 02. 2021, 14:46:45 od Mlocik97 »


Re:Python zaokruhlovanie na cele cislo nefunguje spravne
« Odpověď #35 kdy: 21. 02. 2021, 20:54:21 »
Tohle je jadro pudla naseho sporu. Nesouhlasim a schvalne to vic rozvedme.

Mam ceni vyrobku v excelu. Tento cenik budu jistojiste mit s presnosti na 1 desetinne misto (desitky haleru). Kdyz budu chtit zvysit ceny o inflaci, tak je zvednu o inflaci, nacez 2. desetinne misto zaokrouhlim klasickou metodou:

10.50,- CZK -> + 3% inflace -> 10.815,- CKZ -> 10.8 CZK

Ukazte mi, v cem je podle vas problem se zaokrohlovanim.
Máme původní cenu 10 Kč, inflaci 3,5 %. Po vynásobení vyjde nová cena 10,35 Kč. Ceny chceme uvádět v desítkách haléřů. 10,35 Kč je stejně daleko od 10,3 Kč i 10,4 Kč. Když budu zaokrouhlovat vaším způsobem, budou tyhle „nerozhodné“ případy (s 5 halíři na konci) vždy zaokrouhlené na vyšší cenu, ve prospěch obchodníka. Když si pak udělá na konci kontrolu – sečte všechny staré ceny a všechny nové ceny, zjistí, že zdražil o něco víc než jen o inflaci 3,5 %.

Vy jste totiz strasne komplikovany clovek. Chapete to, ze 99.9% lidi, a dokonce i programatoru, staci bohate klasicky typ zaokrouhlovani, tzn. ten co jsme se vsichni na cele planete naucili v 6. tride?
Šmudlalům je to jedno – tak proč jim rovnou do ruky nedat zaokrouhlování, které funguje lépe než to vaše. No a lidé, kteří dělají práci pořádně, budou sami pátrat po tom, jaké zaokrouhlování nejlépe použít

A co me stve je, ze velevazeny Python, ktery si hraje na jazyk radoby jednoduchy a pro zacatecniky, obsahuje ve std lib takovou netradicni a zavadejici metodu zaokrouhlovani. Neni to prvni ani posledni bizarnost se kterou jsem se u Pythonu sektal.
Na té metodě není nic netradičního ani zavádějícího. Zaokrouhlování na sudé se používá naprosto běžně, protože neposouvá výsledky systematicky jedním směrem a je deterministické. Nevím, jestli má nějakou výhodu oproti zaokrouhlování na liché, ale prostě se všeobecně používá zaokrouhlování na sudé. To, že je Python jednoduchý jazyk pro začátečníky, neznamená, že nemůže věci dělat pořádně. Že vy jste se v matematice zasekl v 6. třídě je váš problém, ale není to důvod, proč by se Python měl přizpůsobovat vašim neznalostem.

Re:Python zaokruhlovanie na cele cislo nefunguje spravne
« Odpověď #36 kdy: 22. 02. 2021, 00:06:32 »
docela mě překvapuje, kolik lidí neví, jak počítače počítají s float a jaký v tom vznikají chyby. My přemýšlíme v desítkové soustavě, počítače v dvojkové, obě nejsou navzájem jednoduše převoditelná pro všechna reálná čísla. A ano, "počítače" neumí počítat.

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. Postupně se tenhle algoritmus etabloval napříč celým IT. Drtivá většina jazyků počítá float čísla nepřesně a zaokrouhluje během výpočtu interně, protože to jinak neumí.

Pokud potřebuji počítat přesně (účetnictví, peníze, měření), mám snad v každém jazyku k dispozici datový typ Decimal nebo cokoliv s binary floating point, pořád se ale musím vejít do určité přesnosti, chci-li počítat s neomezenou přesnosti, také to mohu dělat, vše je ale za cenu výkonu, který klesá i řádově.

V bankách vše běží na decimal, ať už v javě nebo v databázi. Dokonce i Cobol, který banky ještě dnes používají v některých systémech nemá neomezenou přesnost a musí se programy správně psát.

_Jenda

  • *****
  • 1 550
    • Zobrazit profil
    • https://jenda.hrach.eu/
    • E-mail
Re:Python zaokruhlovanie na cele cislo nefunguje spravne
« Odpověď #37 kdy: 22. 02. 2021, 02:37:25 »
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?

docela mě překvapuje, kolik lidí neví, jak počítače počítají s float a jaký v tom vznikají chyby.
Mě ani tak nezarazilo, že tohle někdo neví (málokdo potřebuje analyzovat přesnost numerických výpočtů, my taky neznáme detaily spousty jiných podoborů), ale to, jakým způsobem tady svoji nevědomost několik lidí prezentuje.

_Jenda

  • *****
  • 1 550
    • Zobrazit profil
    • https://jenda.hrach.eu/
    • E-mail
Re:Python zaokruhlovanie na cele cislo nefunguje spravne
« Odpověď #38 kdy: 22. 02. 2021, 02:43:52 »
Pokud nechci at se mi posunuje vysledek jednim smerem pri vypoctech, tak sakra himl hergot fix NEZAOKROUHLUJU!!! Pocitam s floaty tak jak vysly!
A to snad není zaokrouhlování? Float má pevně dlouhou mantissu, a výsledky běžně počítaných funkcí (i třeba pouhé sčítání čísel když to zrovna náhodou nevyjde „hezky“) se musí zaokrouhlit, aby šly reprezentovat.

Vsak jo, ale at se zaokrouhli, az kdyz se jdou reprezentovat, a ne v procesu vypoctu.
Už mi asi došlo kde jsme se nepochopili: reprezentací jsem nemyslel konečné vytištění výsledku uživateli, ale to, že FPU dospěla k nějakému výsledku, a teď ho potřebuje vrátit jako 32bit/64bit float. A tam se musí někdy zaokrouhlovat z principu (příklad: sqrt(2)) a někdy protože má výsledek víc bitů mantissy než se vejde do floatu.

Re:Python zaokruhlovanie na cele cislo nefunguje spravne
« Odpověď #39 kdy: 22. 02. 2021, 08:37:12 »
ako riesenie je jednoduche staci pouzit kniznicu math a je to ok ale velmi ma to prekvapilo. Ja som sa v skole ucil ze od X.0 po X.4 sa zaokruhluje hore a od X.5 po X.9 zasa hore.
Rada o tom ako pripocitat +0.5 je chybna. To nie je spravna cesta.
Jenda a ked sa neda pouzit float? Napriklad ja citam data s DB kde je hodnota bud XXXX.5000 alebo 0.XXX podla toho viem su to litre alebo ml musim spravit konverziu a nakoniec to zaokruhlit na cele cislo smerom hore a vysledny format je INT ktory sa zapisuje do zariadenia ktore proste nevie co je float.

Celkovo dakujem za diskusiu okolo zaujimave citanie a myslim ze to pomoze viac ludom.


Re:Python zaokruhlovanie na cele cislo nefunguje spravne
« Odpověď #40 kdy: 22. 02. 2021, 08:49:30 »
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?
To se takhle obecně nedá říct, jestli je to přesnější nebo méně přesné. IEEE 754 bylo zvoleno tak, aby co nejvíc pokrývalo čísla, se kterými běžně počítáme. Pokud budu chtít počítat astronomické vzdálenosti v kilometrech nebo subatomární rozměry v metrech, nebudu počítat ve float ani double, protože v prostoru reprezentovatelných hodnot budu mít obrovské množství čísel, která pro mé použití budou k ničemu, a použitelný prostor hodnot se mi velmi smrskne.

AoK ale podle mne myslel repezentaci ve 32 nebo 64 bitech. Když čísla v počítači reprezentujeme stejně, jako na papíře – desítkově s počtem číslic omezeným jenom tím, kolik jsme toho ochotní zapsat, máme čísla v počítači přesná. Ale rychlost výpočtu tím velmi utrpí.

Mě ani tak nezarazilo, že tohle někdo neví (málokdo potřebuje analyzovat přesnost numerických výpočtů, my taky neznáme detaily spousty jiných podoborů), ale to, jakým způsobem tady svoji nevědomost několik lidí prezentuje.
Mne teda zaráží i to, kolik programátorů to nezná. Tohle je věc, která se všude říká a je všude napsaná, jakmile dojde na čísla s plovoucí řádovou čárkou. Navíc je to věc, na kterou se nedá snadno přijít, pokud o ní člověk neví – dozví se to až z nějakého průšvihu z produkčního nasazení. U toho zaokrouhlování je to trochu něco jiného – tam by si člověk může uvědomit, že pětka je přesně uprostřed a že tedy zaokrouhlování „pětka vždy nahoru“ je nespravedlivé. Pak může začít pátrat po tom, zda to neřešil už někdo před ním – a zjistí, že řešil a že principů zaokrouhlování je spousta.

Ale ta prezentace nevědomosti je skutečně zarážející. Že si někdo nepřečte dokumentaci před tím, než funkci použije, to se dá pochopit – když o různých způsobech zaokrouhlování neví, nečeká v tom žádnou záludnost. Ale že si ji nepřečte ani po té, když narazí na problém, a místo toho metodou pokusu a omylu zkouší, které případy fungují jinak, než čekal, to je zarážející. Že si pak stále nepřečte dokumentaci a místo toho nadává v diskusním fóru, to už je donebevolající. A že se pak přidají další a nadávají těm, kteří to správně vysvětlí, pro to už nemám slov.

Re:Python zaokruhlovanie na cele cislo nefunguje spravne
« Odpověď #41 kdy: 22. 02. 2021, 08:55:56 »
Rada o tom ako pripocitat +0.5 je chybna. To nie je spravna cesta.
Proč by to nebyla správná cesta? Přičíst 0,5 a pak oříznout desetinnou část je (pro nezáporná čísla) přesně to samé, jako zaokrouhlovat 0,5 nahoru (o záporných číslech vy jste také nic nepsal).

Jenda a ked sa neda pouzit float? Napriklad ja citam data s DB kde je hodnota bud XXXX.5000 alebo 0.XXX podla toho viem su to litre alebo ml musim spravit konverziu a nakoniec to zaokruhlit na cele cislo smerom hore a vysledny format je INT ktory sa zapisuje do zariadenia ktore proste nevie co je float.
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.

Re:Python zaokruhlovanie na cele cislo nefunguje spravne
« Odpověď #42 kdy: 22. 02. 2021, 11:36:00 »
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í.