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

XHTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>

Powered by WordPress with Pool theme design by Borja Fernandez.
Entries and comments feeds. Valid XHTML and CSS. ^Top^