Computers houden van accountants
Arnout van Kempen over rommelen in een digitale wereld.
Ik ben eerder wat makkelijk over het type van variabele en functies heengestapt. De types void en int hebben we gezien, maar C kent er nog heel wat meer. Computers rekenen zelf in vaste blokken van veelal 8 cijfers, of een veelvoud daarvan, waarbij ieder cijfer 0 of 1 is. Een cijfer is een bit, 8 cijfers maken een byte, meer bytes een word, en vanaf daar wordt het wat onduidelijker. Het verschilt per computer met welke word-lengte deze rekent. En omdat C dicht aansluit bij de taal van de computer zelf, weet je in C ook niet helemaal zeker wat nu precies de word-lengte is, en dus wat de hoogste waarde van een bepaald type is. Daarom komt C met een header-file, waarin de maximale waardes per type voor die specifieke computer zijn opgenomen: limits.h
Ook een aardige om te bedenken: een computer kent geen min-teken. Daarvoor wordt meestal één bit gebruikt, en dat betekent weer dat de maximale waarde van een getal met plus/min teken een bit korter is dan zonder.
Wat is nu zo aardig van computers? Zolang je met gehele getallen werkt, weten ze daar razendsnel en foutloos mee te werken. En als je bedenkt dat geldbedragen, mits uitgedrukt in centen, ook altijd gehele getallen zijn, dan snap je waarom computers van accountants houden: ze werken beide met hetzelfde soort getallen. Wetenschappers, daar hebben computers heel wat meer moeite mee, maar daar komen we zo op.
Overigens, computers werken uitsluitend met getallen bestaande uit de cijfers 0 en 1. Ze werken dus ook niet met letters, met teksten. Om dat op te lossen zijn we al heel vroeg gebruik gaan maken van een codering waarbij iedere letter door een getal wordt voorgesteld. De bekendste variant is de American Standard Code for Information Interchange, ASCII. Dit is een 7-bits code die tegenwoordig meestal wordt uitgebreid naar 8 bits om diakritisch tekens en dergelijke mogelijk te maken. Dit gebruik van 8 bits, een byte dus, om tekst ofwel characters weer te geven, is zo bekend, dat het kleinste integer-type in C zelfs char heet.
Naast integers, bytes en words dus, kent C ook zogenaamde floating point getallen. Dit is een notatie die door computers veel gebruikt wordt voor grote getallen en voor breuken, met als notering 0.xxx * 10^y. Hierbij is het aantal x-en bepalend voor de nauwkeurigheid, en y bepalend voor de maximale grootte van het getal. Dit soort getallen is voor de computer onnatuurlijk en dus nooit helemaal exact.
Zo krijg je als meest gebruikte types:
char | 1 byte | |
unsigned char | 1 byte | 0 tot 255 |
signed char | 1 byte | -128 tot 127 |
int | 2 of 4 bytes | -32.768 tot 32.767 bij 2 bytes |
unsigned int | 2 of 4 bytes | 0 tot 65.535 bij 2 bytes |
short | Altijd 2 bytes | |
unsigned short | Altijd 2 bytes | |
long | 4 bytes bij 32-bits systeem 8 bytes bij 64-bits systeem |
|
unsigned long | ||
long long | ||
Etc etc | ||
float | 4 bytes | |
double | 8 bytes | |
long double | 10 bytes |
In de accountantspraktijk lijkt het me sterk dat je ooit de enorme getallen nodig gaat hebben die je met een long double kan maken; voor een nauwkeurige interest-berekening zou je bijvoorbeeld aan een float veelal genoeg hebben. Hetzelfde geldt voor de integers. Als je geldbedragen met twee cijfers nauwkeurig achter de komma wilt gebruiken is een long echt genoeg, zelfs als je de administratie van een compleet continent wil voeren. Zelfs met een plus- of minteken is het bereik van een long op een moderne 64-bits computer immers al ruim 90 biljard. Als je programma’s gaat schrijven die zowel op 32-bits als op 64-bits computers moeten werken, dan zou je voor de grote bedragen bij voorkeur een long gebruiken, omdat een int net te kort kan blijken.
Ik heb in de kmc-repo op github twee kleine programmaatjes geplaatst waarmee je kan testen wat de maximale waarden van de verschillende types op jouw computer zijn. Op mijn Pi kan een signed integer tot 21 miljoen gaan bij 2 cijfers achter de komma. Dat zal in de praktijk toch wat aan de kleine kant zijn als je in de administratie van een bedrijf wil gaan grutten. Vandaar, long voor de grotere bedragen.
Tenslotte nog een op het oog wellicht bizar verschijnsel, maar voor computers totaal voor de hand liggend: als een integer zijn maximum bereikt heeft en je telt er toch nog 1 bij op, dan is de nieuwe waarde 0. Als je bedenkt hoe een computer rekent, binair en met een vaste lengte van ieder getal, valt dat wel te snappen. Maar al programmerend moet je er wel rekening mee houden. Immers, als het type char is, dus 1 byte, dan:
255 + 1 < 255
En daar ga je in de praktijk nog wel eens tegenaan lopen. Draai het navolgende programma maar eens, om te zien wat er in de computer echt gebeurt:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char a=250;
for( int t=250; t<270; t++)
{
++a;
printf("t = %d a= %d\n",t ,a);
}
return 0;
}
Het laat een char, a, oplopen van 250 to 270, naast een int, t. Beide variabelen worden steeds met 1 verhoogd, waarbij t gebruikt wordt om te bewaken dat dit stopt na 270. Aan de output zie je dat a na het passeren van 255 weer 0 wordt.
Overigens zit in dit programmaatje nog een aardigheidje van C dat je in de output zal terugzien: je kan een variabele met 1 verhogen door ++ voor of achter de variabele te zetten, en omgekeerd verlagen met — er voor of er achter. In dit programma staat de ++ achter de t, en voor de a. In de output zie je het verschil, als het goed is.
Gerelateerd
We gaan diep!
Arnout van Kempen over rommelen in een digitale wereld.
Herhalingen
Arnout van Kempen over rommelen in een digitale wereld.
Voorwaarden in COBOL
Arnout van Kempen over rommelen in een digitale wereld.
Het Y2K-probleem
Arnout van Kempen over rommelen in een digitale wereld.
Over bits & bytes
Arnout van Kempen over rommelen in een digitale wereld.