Linux - Friheden til at programmere i C: Programmering med GNU/Linux; Version 2.0.20041104 - 2020-12-31 | ||
---|---|---|
forrige | Kapitel 1. Repræsentation og modeller | næste |
Lad os se på, hvordan computeren repræsenterer tal. Det er vel det, den er bedst til? Jo, måske nok, men alligevel, der er faktisk en hage eller to ved computerens måde at repræsentere tal på.
Fx. taler vi om heltal, de naturlige tal, tallene fra 0 og opefter. Eller er det fra 1 og opefter ;-) Nå, i hvert fald så siger vi, at vi kan repræsentere heltallene med en computers kalkulator register eller en memory celle. Men det er ikke helt rigtigt! Det er nemlig kun et udsnit af de naturlige tal, som vi kan repræsentere. Så ikke engang denne enkle opgave kan en computer klare så godt som en almindelig dødelig! Forklaring følger.
Et register er en slags tælleværk, der i dag typisk består af 32 bits - binary digits. De enkelte digits er lavet ved hjælp af et transistor mønster, der kan være i to tilstande, enten i en tilstand, hvor strømmen kan passere, eller også i en tilstand, hvor strømmen blokeres. Når der er 32 bits, kan de danne ca. 4 mia. mønstre eller kombinationer af on/off, 0 eller 1. Det er maximum antal kombinationer. Hvis vi altså tæller fra 0, kan vi komme op på 4 mia med et 32-bit register.
Det er derfor, at der har været en grænse for filstørrelser på de almindeligst forekommende filsystemer. Siger 2 Gb grænsen dig noget? Det er den største fil på for eksempel Linux' ext2-filsystemer. Det kunne have været en 4 Gb grænse, men én af bit'ene er reserveret til et andet formål, nemlig til angivelse af, om systemet er i en fejltilstand efter en skrive- eller læseoperation. En bit, on/off, svarer altså til en fordobling af kombinationsmulighederne, se nærmere nedenfor.
Bits er altså repræsenteret ved hjælp af elektriske kredsløb, der kan aflæses af andre kredsløb.
Kalkulator registeret, det vigtigste register på den traditionelt opbyggede CPU, er en slags tælleværk bestående af bits (i dag som regel 32), som en kilometertæller, som kan udføre forskellige regnestykker på det tal, den indeholder.
En CPU kan have mange kalkulator-registre. De har navne, ofte noget med R1 og R2, i Intel-arkitekturen (x86 - CPU'er) hedder de imidlertid EAX, EBX, ECX etc (hvilket er copyrighted!) Mange af dem kan udføre regnestykker. På Intel 386 arkitekturen (og Pentium m.v.) kan man dog se en vis fortrinsstilling for EAX registeret. Men denne bog handler ikke om Intel. Hvis Intels CPU'er interesserer dig, så hent fra www.intel.com "Intel Architecture Software Developer's Manual" (det er 3 PDF-filer på ialt omkring 15 Mb), eller find en bog om assemblerprogrammering, eller prøv at læse den Assembly-HOWTO, som følger med bl.a. Red Hat Linux.
Hvis CPU-en har 32-bit registre, så kan man skrive tal fra 0 til 4 milliarder. Selv om det er mange, er det ikke ALLE de naturlige tal - de fortsætter jo opefter, mod uendelig, som man siger. Selv om det heller ikke er muligt at finde noget i universet, som er uendeligt, man bliver om jeg så må sige træt inden man når dertil, er det alligevel en mere begrænset repræsentation af talsystemet, som vi får med en 32-bit computer [1] Metoden til at tælle ved hjælp af bits, som du sikkert kender eller allerede har regnet ud, kan illustreres med følgende tabel (med kun 4 bit):
ottere | firere | toere_ | enere_ | værdi med almindeligt 10-talsystem |
---|---|---|---|---|
0 | 0 | 0 | 0 | == 0 |
0 | 0 | 0 | 1 | == 1 |
0 | 0 | 1 | 0 | == 2 |
0 | 0 | 1 | 1 | == 3 |
0 | 1 | 0 | 0 | == 4 |
0 | 1 | 0 | 1 | == 5 |
0 | 1 | 1 | 0 | == 6 |
0 | 1 | 1 | 1 | == 7 |
Som man kan se kan kolonnerne kaldes ENERE, TOERE og FIRERE i analogi med vores ti-tal system, hvor vi siger, at kolonnerne repræsenterer enere, tiere og hundreder etc.
Hvis vi har brug for mere, kan vi imidlertid godt sætte flere registre, eller flere memory celler, sammen, så vores tal kan blive større. Det er forholdsvis enkelt.
De negative tal kunne vi repræsentere ved at markere med en ekstra bit (eventuelt et helt andet sted) at vi skulle gange med -1. Nogle maskiner kan faktisk skelne mellem +0 og -0! Men det er ikke populært i dag. Man vælger som regel en anden metode.
Man indretter CPU registrene sådan, at når man tæller op, så bliver 1...1111 til 0...0000 (for ikke at skrive alle 32 bit, skriver jeg 1...1111.) Det ligner lidt en kilometertæller, som når den har nået det største tal, den kan vise, går tilbage til 0, altså for eksempel går fra 99999 til 00000.
Men altså, det skal forestille, at alle bit er tændt - det kalder man, at de er sat. Hvis det er et 32-bit register, svarer det til ca. 4 milliarder. Når man så lægger 1 til, bliver resultatet 0! Det ligner ikke helt den verden, vi ønsker at repræsentere med vores computer programmer. Derfor bør man under programmering altid være opmærksom på grænserne for de tal, man arbejder med. Det er imidlertid ikke så slemt, som det lyder.
Altså, når alle bit er sat, og vi lægger en til, så slukker de alle sammen. Derfor kunne det være en god idé at lade 1...1111 repræsentere det negative tal -1.
fortegn | _______ | _______ | _______ | værdi med almindeligt 10-talsystem |
---|---|---|---|---|
1 | 0 | 0 | 0 | == -8 |
1 | 0 | 0 | 1 | == -7 |
1 | 0 | 1 | 0 | == -6 |
1 | 0 | 1 | 1 | == -5 |
1 | 1 | 0 | 0 | == -4 |
1 | 1 | 0 | 1 | == -3 |
1 | 1 | 1 | 0 | == -2 |
1 | 1 | 1 | 1 | == -1 |
Som man kan se, nytter det ikke noget her at kalde kolonnerne for ENERE, TOERE og FIRERE. Hvis man skal give denne "konvertering af betydningen" et navn, så plejer man at kalde den 2's komplement. Men egentlig er det 232's komplement, d.v.s. 232-tal.
Det er nok lettere at se det for sig med en illustration. Man repræsenterer f.x. 1 med en bit i den ene ende. Når man vender alle bits om, så 0'er bliver til 1 og omvent (inverterer), og lægger 1 til, så får man bitmønsteret til repræsentation af -1.
Eksempel 1-1. tallene fra 0 til 7 og 0 til -7.
0: 0000, Inverted: 1111, Complement(til 2^4): 0000 1: 0001, Inverted: 1110, Complement(til 2^4): 1111 2: 0010, Inverted: 1101, Complement(til 2^4): 1110 3: 0011, Inverted: 1100, Complement(til 2^4): 1101 4: 0100, Inverted: 1011, Complement(til 2^4): 1100 5: 0101, Inverted: 1010, Complement(til 2^4): 1011 6: 0110, Inverted: 1001, Complement(til 2^4): 1010 7: 0111, Inverted: 1000, Complement(til 2^4): 1001
Når der er tale om 32 bit heltals repræsentation, er det lettere at benytte hexadecimal notation. Tallene fra 0-9 skrives som sædvanlig 0-9, men 10-15 skrives a-f. Det betyder, at man kan repræsentere 4 bit med ét 'ciffer', hvor ciffer skal forstås som 0-9a-f.
Eksempel 1-2. tallene fra 0 til 7 og 0 til -7.
Word: 00000000, Inverted: ffffffff, Complement: 00000000 Word: 00000001, Inverted: fffffffe, Complement: ffffffff Word: 00000002, Inverted: fffffffd, Complement: fffffffe Word: 00000003, Inverted: fffffffc, Complement: fffffffd Word: 00000004, Inverted: fffffffb, Complement: fffffffc Word: 00000005, Inverted: fffffffa, Complement: fffffffb Word: 00000006, Inverted: fffffff9, Complement: fffffffa Word: 00000007, Inverted: fffffff8, Complement: fffffff9
Fortsætter man denne tankegang, så bliver det største tal med 32 - bit ca. 2 milliarder, og det er stadigvæk en pæn sjat.
Grunden til, at Linux' ext2-filsystem ikke kan have filer, som er større end 2 Gb er forresten, at grænsesnittene der bruges til at læse og skrive filer arbejder med 32 bit heltal (hvoraf en bit bruges til fortegnet).
Et program, som frembringer udskriften ovenfor (fig Eksempel 1-2) er vist i Afsnit 2.7.
Det er muligt at repræsentere tal på andre måder end den her viste. Men vigtigere, det er muligt at repræsentere andet end tal. Bogstaver kan repræsenteres ved hjælp af tal, den simpleste løsning på en computer med mulighed for at repræsentere tekst er jo den kendte metode med en byte pr. bogstav. Det er ikke nok, hvis der også skal være plads til at repræsentere græske bogstaver, matematiske symboler, og slet ikke, hvis også forskellige grafiske symboler, skrifttypebeskrivelser etc. skal repræsenteres. Men det er en helt anden historie.
Andre ting, som for eksempel grøntsager og frugt, må repræsenteres ved bits og bytes på samme måde som tal og bogstaver. Hvis du er ny i programmering, vil det klogeste være at afprøve nogle programmer nu, måske endda bruge 3 - 4 måneder på eksemplerne og øvelserne i Afsnit 2.1 kapitlet. Hvis du på den anden side kender lidt til programmering og gerne vil køre tanken om repræsentation til ende, så er der to begreber, som vi skal tygge lidt på: Simuleringer og modeller.
[1] |
En lidt mere seriøs beskrivelse af tid, uendelighed og rum kan man finde i Stephen Hawking's "Brief History Of Time", nej, ikke Stephen King! |