Citat:
Ursprungligen postat av
CaptainThundree
Någon som grundläggande kan berätta hur man kodar följande ekvation.
"Enligt Dolbears lag (
https://sv.wikipedia.org/wiki/Dolbears_lag) kan luftens temperatur beräknas utgående från frekvensen hos en syrsas spel, enligt följande formel:
Tc = 10 + (N60 - 40) / 7
Du har redan uttrycket, börja med att smälla dit ett semikolon efter. Sen bestämmer du vilken/vilka typer som är lämpliga, ser upp för att /-operatorn utför heltalsdivision om båda operanderna är heltal, samt funderar på eventuell over-/underflow. Fast det sistnämnda brukar vara skitsamma när det är en skoluppgift.
Uttrycket evalueras i matematisk ordning (parenteser har högre prioritet än multiplikation och division, som har högre prioritet än addition och subtraktion) och innan varje aritmetisk operation konverteras en av operanderna till den andra operandens typ så att de blir samma. Resultatet av operationen blir såklart också den typen. Generellt är reglerna dessa:
* Med två flyttalstyper av olika storlek, konverteras den mindre till den större. Detsamma gäller två signade typer av olika storlek och två unsignade av olika storlek. Inga problem där.
* Om en av operanderna är flyttal och den andra heltal, konverteras heltalet till flyttalets typ. Det enda problemet där är att man kan förlora precision.
* Försök att inte blanda signed och unsigned utan att cast:a. Regeln för konvertering i standard C beror på om den signade typen kan hålla alla den unsignade typens värden, vilket kan variera mellan olika system. I traditionell C var regeln dessutom en annan.
Heltalstyper har fördelen att alla beräkningar sker exakt, men nackdelen att de kan under-/överflöda. Unsigned-typer wrappar runt, medan signed-typer ger odefinierat beteende. Flyttalstyper har nackdelen att de förlorar precision, men fördelen att det ska mycket till innan de flödar och jag tror inte att de kan ge odefinierat beteende. Man kan bestämma typen själv m.h.a. en cast, och för konstanter går det även att använda t.ex. postfixen U (unsigned), L (long), eller skriva dem som ett flyttal med e-notation eller ".0" efter.
`N60 - 40` evalueras först. Konstanten 40 är garanterat en int eftersom en int kan hålla minst 32678 på alla system (en längre konstant kan bli long, eller long long i C99) och N60 är det du har deklarerat den som. Även om denna är en flyttalstyp (och det är flyttalsaritmetik du vill ha) så att 40 automatiskt blir konverterad till flyttal, skulle jag rekommendera att skriva 40.0 ifall du ändrar typen på N60 senare.
Sen delas resultatet med 7, som också är en int. Samma här: Om resutatet av `N60 - 40` är flyttal, konverteras 7 till 7.0 men det är bättre att specifikt skriva 7.0 om det är flyttalsberäkningar du vill ha hela vägen. Om resultatet av `N60 - 40` är heltal, kommer resultatet av divisionen också att bli ett heltal genom att decimaldelen klipps bort, så t.ex. 5 / 7 blir 0. Denna introducerade jätteavrundning kan ställa till det i resten av uttrycket. Som exempel spelar det ingen roll vad du multiplicerar 0 med, det blir ändå bara 0. Men i det här fallet gör det inget om du ändå ska avrunda hela svaret till ett heltal, för det enda du gör efteråt är ju att addera 10.
EDIT: Innan justeringen för att båda operanderna ska få samma typ, sker eventuell konvertering av båda operanderna separat så att de blir minst unsigned int, int eller float (minst double i traditionell C). Inga operationer utförs med t.ex. två signed char, utan två sådana med värdet 100 kommer att ge en int med värdet 200, och inte överflöda en 8-bitars signed char. Vid denna konvertering kan samma problem uppstå som när man blandar signed och unsigned: unsigned char och unsigned short konverteras till int om den typen kan hålla alla värden, annars unsigned int. På t.ex. ett system där både int och short är 16 bitar, kommer typen att bli annorlunda än om int är 32 bitar. Cast:a om du vill vara säker på vilken typ du får.