Leo: | Als je twee verschillende getallen van elkaar aftrekt hoort er geen nul uit te komen, zou ik zo zeggen. Moet ik om Forth te leren ook nog mijn algemene inzichten in het rekenen met getallen bijstellen? Dat is te veel gevraagd. |
Theo: | Het zit zo: Deze Forth werkt met de getallen van -32768 tot en met 32767. Dat komt doordat hij getallen opslaat in een patroon van 16 bits. Getallen die groter of kleiner zijn passen niet meer in die 16 bits, want je kunt met 16 bits hoogstens 65536 (= 2 in de macht 16) verschillende patronen maken. |
Leo: | Maar waarom slikt hij die 40000 dan toch? |
Theo: |
Je hebt gelijk, in een andere programmertaal zou er waarschijnlijk
een foutmelding komen.
Toch heeft het zin dat hij die 40000 goedkeurt. Ik zal je uitleggen waarom.
Je kunt het hele getallengebied van -32768 via 0 naar 32767 doorlopen door er steeds 1 bij op te tellen. Aan de rand van het gebied gebeurt er dit: 32767 1 + . [rtn] -32768 okAls je het grootste getal met 1 verhoogt komt het kleinste getal als antwoord te voorschijn! Er treedt een overflow op, d.w.z. er onstaat een bitpatroon van 17 bits, maar Forth laat die 17de positie gewoon weg waardoor de reeks patronen weer opnieuw begint en al de getallen als het ware op een cirkel komen te liggen. Gevolg: als je twee getallen bij elkaar optelt komt er altijd een antwoord uit. De programmeur moet zelf in de gaten houden of dat antwoord juist is, anders gezegd, zonder overflow tot stand gekomen is. Naast dit systeem (de SIGNED getallen) bestaat er een tweede systeem (de UNSIGNED getallen) dat met precies dezelfde bitpatronen werkt. Hierin blijven de positieve getallen hetzelfde maar alle negatieve getallen worden over boord gezet om er aan de bovenkant als hoge positieve getallen weer bij geplakt te worden. De UNSIGNED getallen lopen van 0 naar 65535. Die hoge positieve getallen moeten ook ingevoerd kunnen worden en daarom werd 40000 dus geaccepteerd. Forth onthoudt alleen het getal als bitpatroon en niet de manier waarop het binnengekomen is. Aan de randen van het gebied treedt weer het overflow effect op: 65535 1 + . [rtn] 0 okMaar nu terug: 0 1 - . [rtn] -1 okDit gaat fout, want.. de PUNT weet niet dat het hier om een UNSIGNED getal gaat. 65535 1 + U. [rtn] 0 ok 0 1 - U. [rtn] 65535 okDe + en de - werken goed voor beide systemen. Voor afdrukken, maar ook voor vergelijken heb je aparte commando's nodig: . U. < U< > U> En de oplossing voor je MAX -probleem is dus het definiëren van een UMAX met U< erin. |