Dělení v C/C++
September 30, 2006 on 9:12 am | In Archive |To jsem se zase jednou docela dlouho hádal s compilerem, takže si důvod a řešení musím někam napsat - no a znáte lepší místo než blog?
Takže hádka proběhla v asi 9:15 SEČ v počítačové učebně MGP. Verzi GCC si již bohužel nepamatuji… (to ale to nevadí, compilerem to jako obvykle totiž nebylo) Zadaní je jednoduché - nekonečné řady. O co jde? Prostě o počítání 1/1 + 1/2 + 1/3 + 1/4 + 1/5 + 1/6 … Samozdřejmě že PC něco jako nekonečno neuznávají, takže výpočet je ukončen pomocí přesnosti (neřešte - není důležité).
V programu jsem měl zápis (úryvek):
double S1 = 0;
int delitel = 1;
…
do
{
S1 += 1/delitel;
delitel++;
} while(…);
Že Vám na tom nepříjde nic divného? No je tam chyba - schválně kdo ji najde. Mě to třeba trvalo docela dlouho…
Takže v čem je zakopaný pes?
V operátoru dělení - pokud totiž při dělení použijeme dvě celočíselné hodnoty, tak C++ (nejen, dělá to i normalní C) použije instrukci procesoru DIV. Tzn. čísla děli bez desetiných částí. Co to znamená ve výsledku? 1/1 je 1 o tom žádná, ale 1/2 není jak by jsme očekávali 0.5, ale 0 a zbytek 1. 0 se poté uloží do proměné double a zbytek se zahodí. Takže de-facto poté už k proměné S1 nic nepřičítám…
Takže jak to opravit? První řešení co mě napadlo je změnit typ proměné delitel na double, což ovšem dle mého názoru není chytré - double zabíra v paměti 8 bytů oproti 4 bytům u intu. Jiné řešení je nechat deliteli typ int a při dělení ho explicitně konvertovat na double:
S1 += 1/double(delitel);
což (přiznejme si) vypadá strašně, takže bude lepší convertovat první člen. Způsoby jsou opět dva:
S1 += double(1)/delitel;
nebo
S1 += 1.0 / delitel;
Jak Vám asi došlo, tak nejkrásnější je poslední způsob, který jsem nakonec i použil. Otestování které z mnou nabízených řešení je nejrychlejší už ovšem nechám na čtenáři…
No Comments yet »
RSS feed for comments on this post. TrackBack URI
Leave a comment
Powered by WordPress with Pool theme design by Borja Fernandez.
Entries and comments feeds.
Valid XHTML and CSS. ^Top^