Uitwerking Opgaven Programmeermethoden, najaar 2020 - opgaven 1/5 Opgave 1 a. De functie sqrt komt uit cmath; bovenaan het programma moet dus de regel #include staan, terwijl er soms met -lm (helemaal aan het eind van de regel g++ -o ...) gecompileerd moet worden. Vroeger heette dit math.h overigens. De functie geeft met een int(eger) of double als invoer een double als uitvoer. Resultaat is hier 2 (oftewel 2.0000). b. Wederom 2 (oftewel 2.0000). c. Er wordt dikwijls "automatisch" tussen char's (karakters) en int's geconverteerd. In sommige talen is daar een speciale omzetfunctie voor nodig, in C++ niet. Aangezien verder de karakters 'a', 'b', ... een oplopend (met stap 1) rangnummer hebben in de ASCII-tabel -en dat is de corresponderende getalswaarde- komt er het aantal letters "tussen" 'e' en 't' uit: 15 dus. Het minteken forceert als het ware de omzetting naar int's. d. De functie ceil rond naar boven (naar rechts op de getallenlijn) af. Resultaat is -99 (een double). e. En floor rondt naar beneden af. Dus -99. f. Dit geeft de double 100. g. Het is een expressie van type bool(ean). Moderne compilers hebben dit type als bool, bij heel oude compilers moet je het zelf nog maken via enum boolean {false = 0, true = 1}; Met een waarheidstabel/tafel valt dan in te zien dat de uitdrukking equivalent is aan de exclusieve of: de XOR (oftewel p != q). Stel nu eens dat er een enkele = stond in plaats van een dubbele. Dan mag het opeens niet: de enkele = is een toekenning! Links staat namelijk iets waaraan niet mag worden toegekend (er staat geen "l-value"); expressies als 3*x+5 en !(p&&q) zijn altijd "r-values" (waarden) en mogen alleen RECHTS van de = komen te staan. Het zijn "l-values" als ze een geheugen-locatie aanduiden. Voorlopig zijn dat alleen variabele-namen. h. Rest bij deling van 10 door 3: een int, en wel 1. i. Naar beneden afgerond resultaat van de deling van 10 door 3: een int met waarde 3. Als minstens een van de twee betrokken getallen een double is, wordt het resultaat ook een double. Dit valt ook door "casting" af te dwingen: zo wordt (double) 3 de double 3.0000. Dan levert 10 / (double) 3 de double 3.3333 op. j. Aangezien / en % dezelfde prioriteit blijken te hebben, en "links- associatief" zijn, staat er eigenlijk ( 126 / 3 ) % 5, wat 42 % 5, en dus de int 2 is. Een operator $ is links-associatief als a $ b $ c betekent ( a $ b $ ) $ c. Zo is - (min) links-associatief: 3 - 4 - 5 = (3-4) - 5 = -1 - 5 = -6, en NIET 3 - (4-5) = 3 - -1 = 4. k. Het resultaat is false (ongeacht de waarden van p, q, r en s). q && !q is altijd false, p && false is ook weer false. Het linker argument van de OR, de ||, is dus false. Verder is s || !s altijd true, r || true is ook true, en !true is false. Het rechter argument van de OR is dus ook false. Nu is false || false ook weer false. Klaar. Met een waarheidstafel -met 16 rijen- kan dit ook worden ingezien. l. Het resultaat is de waarde van p. Immers, floor (-65.3) = -66, fabs (-65.3) is 65.3 (absolute waarde), -66 < 65.3 is true, en true && p is p. m. De functie odd (oneven) bestaat niet in C++/math.h. Zou dit wel zo zijn, dan kwam er true uit: k of k+1 is oneven - laten we hopen dat k+1 niet net te groot wordt. De functie odd kan zelf gemaakt worden als: int odd (int a) { return ( ( a % 2 ) == 1 ); } // Is a oneven? Tussen de accolades mag ook return ( a % 2 ); staan. Opgave 2 int main ( ) { int Fahrenheit; cout << "Geef temperatuur in Fahrenheit .."; cin >> Fahrenheit; cout << "In Celsius is dat: " << ( (double) 5 / 9 ) * ( Fahrenheit - 32 ) << endl; return 0; } // main Let er op dat 5 / 9 nul is! Moet er met gehele getallen gerekend worden, gebruik dan: cout << ( 5 * ( Fahrenheit - 32 ) ) / 9; Opgave 3 int main ( ) { int seconden, uren, minuten, secs; cout << "Voer tijd in seconden sinds middernacht in .."; cin >> seconden; uren = seconden / ( 60 * 60 ); minuten = ( seconden - 60 * 60 * uren ) / 60; secs = seconden % 60; cout << "De tijd is " << uren << ":" << minuten << ":" << secs << endl; return 0; } // main Opgave 4 Een lang verhaal. Er zijn allerlei soorten gehele getallen: er is het verschil signed/unsigned, en de drie kwalificaties short/geen/long. Verder kunnen ook char's voor rekenwerk gebruikt worden. Tot slot hangt het misschien zelfs wel af van de implementatie van C++. Laten we proberen te snappen waarom 2 tot de macht 31 - 1 in sommige implementaties van C++ het grootste gehele getal is. Stel dat je 4 bytes, ieder met 8 bits, hebt om een int in op te slaan. Er is een bit nodig voor het teken. Resteren 31 bits. Bij het grootste getal staan deze alle op 1. Zouden het er 3 zijn, dan hadden we (binair) 111 oftewel 4 + 2 + 1 = 7 = 8 - 1. Tel er maar 1 bij op, en je krijgt binair 1000. Bij 31 bits krijg je, na er 1 bij te hebben opgeteld, een 1 met 31 nullen er achter, en dat levert het genoemde getal. Overigens staan de grenzen in climits. Probeer ook eens de functie sizeof (type), die de grootte van het type in bytes geeft. Als je 1 optelt bij het grootste getal krijg je doorgaans het kleinste: de tekenbit wordt vaak omgeklapt door de overflow, vergelijk de 1000 van hierboven. Voor wat betreft de double's: zoek dit zelf eens uit, zie cfloat. Opgave 5 Er wordt natuurlijk gewoon bedoeld if ( doorgaan ) ..., terwijl bovendien er nu een toekenning aan doorgaan wordt gedaan, waardoor de test de waarde van die toekenning (true) krijgt. Zou er while staan in plaats van if, dan krijg je een oneindige loop. Zelfs met == in plaats van = blijft het slap. Opmerking De in deze uitwerkingen gegeven programma's moeten vaak nog van een flinke dosis commentaar voorzien worden!