Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.
Avatar
Honza 211
Člen
Avatar
Honza 211:10.9.2018 13:39

Zdravím,
mám následující problém: pokud v c vynásobím např. 23.69*1000000000, tak mi vyjde 23690000384. Nevíte někdo, kde by mohla být chyba? Tuším, že to bude něco s datovými typy - když násobím o nulu menším číslem nebo desetkrát menší číslo, tak to funguje jak má.
Díky za všechny nápady!

Zkusil jsem: Vyabstrahovat operaci z programu a zkusit to na samostatném kódu.

Chci docílit: Pokouším se o jednoduchý program na převod racionálních čísel na zlomky. Číslo vynásobím třeba právě miliardou a pak v cyklu dělím deseti, dokud nebude zbytek po dělení větší než 0. Zároveň s ním dělím číslo, kterým jsem ho vynásobil a to pak přijde do jmenovatele.

 
Odpovědět
10.9.2018 13:39
Avatar
Odpovídá na Honza 211
Luboš Běhounek Satik:10.9.2018 13:49

V čem máš čísla uložený? Ve floatu?
Desetinný čísla jsou uložený tak, že maj přesnost jen na několik platných číslic - podle toho, jak velkej typ použiješ.

Float to má cca 7 platných číslic, pokud do něj uložíš i celý číslo větší než tuším 16 777 216, tak ti to už může vrátit jiný číslo, než jsi tam uložil, aniž bys s ním dělal nějaký výpočty.

Nahoru Odpovědět
10.9.2018 13:49
https://www.facebook.com/peasantsandcastles/
Avatar
Honza 211
Člen
Avatar
Honza 211:10.9.2018 14:01

Přesně tak, je to float. Pomohl by mi double nebo long double? Víc desetinných míst nepotřebuju, jde mi o tu hranici pro celá čísla, kde už to začíná blbnout. Nebo bych to taky mohl nějak šikovně zaokrouhlit...

 
Nahoru Odpovědět
10.9.2018 14:01
Avatar
Odpovídá na Honza 211
Luboš Běhounek Satik:10.9.2018 14:04

na tohle by jeste mohl stacit double, kam az ty cisla muzou rust?

Nahoru Odpovědět
10.9.2018 14:04
https://www.facebook.com/peasantsandcastles/
Avatar
Honza 211
Člen
Avatar
Honza 211:10.9.2018 14:26

vstupni hodnoty staci do desitek tisic a pri presnosti 6 desetinnych mist by stacilo nasobit milionem a vysledky by se tudiz pohybovaly v desitkach miliard.

Kazdopadne diky za tip, zkusim to predefinovat.

 
Nahoru Odpovědět
10.9.2018 14:26
Avatar
Honza 211
Člen
Avatar
Honza 211:10.9.2018 16:50

Tak double uz nezlobi. Akorat je problem, kdyz si tu hodnotu chci ulozit do int, to se pak z 2350000000 stane -2147483648. Zkusil jsem pretypovat na long a nic. A v intu to mit potrebuju, protoze pouzivam funkci modulo.

 
Nahoru Odpovědět
10.9.2018 16:50
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Honza 211
DarkCoder:10.9.2018 17:20

Operátor modulo % lze použít pro libovolný celočíselný typ.

Nahoru Odpovědět
10.9.2018 17:20
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Odpovídá na Honza 211
Luboš Běhounek Satik:10.9.2018 17:36

2350000000 je mimo rozsah signed 32bit intu -> budto unsigned nebo 64bit int.

Nahoru Odpovědět
10.9.2018 17:36
https://www.facebook.com/peasantsandcastles/
Avatar
Martin Dráb
Tvůrce
Avatar
Odpovídá na DarkCoder
Martin Dráb:10.9.2018 17:36

Pořád se tam můžeš potýkat se zaokrouhlovacími chybami, což je dáno tím, jak jsou interně desetinná čísla uložena v paměti (viz IEEE 754). Vzhledem k jejich reprezentaci třeba není možné přesně uložit čísla jako dvě desetiny – protože nejdou rozložit na konečný součet (byť i záporných) mocnin dvojky.

Pokud potřebuješ přesnost na relativně málo desetinných míst, můžeš desetinná čísla reprezentovat čísly celými. Pokud třeba potřebuješ být přesný na pět des. míst, prostě místo jednotek pracuj se statisíci (v zásadě vše vynásobíš 100000, abyses s des čísly vůbec nesetkal). Pokud ti bude stačit 64bitový integer, tak máš vyhráno.

Navíc, počítání s celými čísly je výrazně rychlejší než z desetinnými (pokud nevyužiješ paralelizační možnosti procesoru či grafické karty).

Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
Nahoru Odpovědět
10.9.2018 17:36
2 + 2 = 5 for extremely large values of 2
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Honza 211
DarkCoder:10.9.2018 20:02

Int, long, unsigned, unsigned long jsou stále mimo rozsah. Proto při převodu z větší hodnoty která je mimo rozsah na menší dochází k nesmyslné hodnotě. Aby si mohl provést operaci modulo s velkou hodnotou, použij datový typ long long, nebo unsigned long long. Tyto typy jsou podporovány od verze C99. Pro výpis pomocí printf() long long použij specifikaci formátu %lli, pro unsigned long long použij specifikaci formátu %llu.

Např:

printf("%lli\n", ((long long)(a*b)) % x);
Nahoru Odpovědět
10.9.2018 20:02
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Honza 211
Člen
Avatar
Honza 211:10.9.2018 20:42

Díky za všechny odpovědi i věcné připomínky. Inu, nováček se sám vytrestal tím, že poznatky o syntaxi a datových typech céčka čerpal pouze z prvního českého zdroje, který mu strejda Google vyplivl - tak o půlce zde zmíněných typech jsem neměl ani páru.

Díky Lubošovi za okamžité a věcné odpovědi, díky DarkCoderovi za syntaxi, jako řešení ale nakonec označím Martina. Myslím, že jeho návrh výrazně zkrátil toto vlákno a šetří čas i nervy ostatních přispěvatelů, protože okamžitým převodem na celá čísla předejdu dalším problémům, které bych zde jinak konzultoval.

 
Nahoru Odpovědět
10.9.2018 20:42
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 11 zpráv z 11.