Många beräkningar är approximationer Ändlig aritmetik Och bitvisa operatorer • Val av modell - Idealiseringar • Fel i indata - Mätvärden med begränsad noggrannhet • Avrundningsfel - Ändlig aritmetik • Trunkeringsfel - ett oändligt värde ersätts med en ändlig 2 Exempel • • Jordens yta beräknas med: A=4!r2 Approximationer modelleras som en sfär radiens värde är ett resultat av tidigare beräkningar värdet ! är ett oändligt värde som måste trunkeras värden och resultat i beräkningarna avrundas … och dessutom så ökar felets storlek pga beräkningarna (bla multipliceras felen med 4) • • • • • Avrundningsregler • • • • Avkorta Avrundning till närmast jämna Vancouver-exemplet Januari 1982 börs index satt till 1000 November 1983 bottennotering 520 index noterades med 3 decimaler och avhuggning Räkningar med avrundningar nästan dubblade index Sida med fler exempel: • • • • http://ta.twi.tudelft.nl/users/vuik/wi211/disasters.html 3 4 Olika typer av fel Heltal(int) • Syntaxfel - Grammatiska fel - Felstavningar - Upptäcks vid kompileringen • Programkörningsfel(run-time error) - Problem som uppstår under programkörning. Avslutar programmet • Semantiska fel (Tankefel) - Problemet är löst på fel sätt, eller man har löst fel problem. - Man får ett felaktigt resultat 5 • Datatypen int används tillsammans med char, short int och long int för att lagra heltal i C. • Matematisk sett finns det oändligt många heltal. På en dator måste det införas en begränsning på hur stora heltalen kan bli. • Normalt sparas ett heltal (int) i ett maskinord, oftast 4 byte (4 * 8 = 32 bitar). 6 Heltal forts. Overflow • Om int lagras som 4 bytes, betyder det att den kan anta 232 olika värden. #include <stdio.h> #include <limits.h> • Hälften av värdena används för att lagra negativa heltal och hälften för att lagra positiva heltal. 2147483647 -2147483648 int main(void) { int x=INT_MAX; printf("%d\n",x); x=x+1; printf("%d\n",x); } • Om i är en variabel av typen int, kan i anta heltalsvärden i intervallet [-231,231-1]. • Eftersom variabler har begränsad lagringskapacitet kan man drabbas av overflow, t.ex. om man försöker multiplicera två variabler vars produkt blir större än det maximala värdet som en variabel kan lagra. Varför blev det såhär? 7 Heltalsrepresentation • Alla variabler oavsett typ representeras internt i datorn som binära tal med ettor och nollor. • Om vi antar att en int representeras med 2 byte (dock vanligare med 4 byte) på systemet. blir den binära representationen: 00000000 00000000 00000000 00000000 00000001 00000111 00001000 00001001 1·20=1 1·22+1·21+1·20=7 1·23+0·22+0·21+0·20 =8 1·23+0·22+0·21+1·20 =9 Bitvisa operationer • I C kan man operera direkt på de enskilda bitarna med de så kallade bitoperatorerna. # Logiska operatorer# unary complement# ˜ " " and" & # # exclusive or# ˆ " " inclusive or" | " Shiftoperatorer" left shift" << " " right shift" >> • Bitvisa operatorer kan enbart utföras på heltalstyper (int, unsigned int, long, char, . . . ). 9 10 Binärt komplement Negativa tal • Med komplementet menas att alla bitar byter värde, dvs alla ettor blir nollor och alla nollor blir ettor. • Negativa tal representeras ofta enligt vad som på engelska kallas ”two’s complement representation”. • Den binära representationen av heltalet int • Det innebär att ett negativt tal -n representeras som det binära komplementet till n-1 0" 00000000 00000000 00000000 00000000 0000000 00001000 01100100 10100111 -1" 11111111 11111111 11111111 11111111 # Uttrycket ˜a blir således 6" 00000000 00000000 00000000 00000110 1111111 11110111 10011011 01011000 -7" 11111111 11111111 11111111 11111001 a = 550055; " (20+ 21+ 22+ 25+ 27+ 210+ 213+ 214+ 219) # är 11 12 Addition Ex1 Addition Ex2 (i en byte för enkelhetens skull) 3+(-2)=1 127 + 1 = -128 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 + 1 1 1 1 1 1 1 0 = 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 + 0 0 0 0 0 0 0 1 = 1 0 0 0 0 0 0 0 Exempel Flyttal • Att reella tal inte lagras exakt kan ge upphov till vissa problem. • Om vi antar att vår dator kan lagra en float med maximalt 5 signifikanta siffror. • En float har vanligtvis en ungefärlig precision av 6 signifikanta siffror och ett ungefärlig omfång (range) på 10-38 till 1038. • Representationen i maskinen blir (i bas 10 i.s.f. 2): • 0.d1d2d3d4d5d6·10n där -38<n<38. • En double har vanligtvis en precision av 15 signifikanta siffror och ett omfång på 10-308 till 10308. • x i satsen float x = 12345F; float y = 1e-1F; float z = 0 / (x + y - 0.12345e5F); /*problem*/ • När uttrycket i nämnaren skall evalueras måste exponenten av de tre talen vara av samma storlek. x=0.12345e5 y=0.00000e5 x+y- 0.12345e5==0 double x = 123.45123451234512345 /* 20 signifikant digits */ # resulterar att x blir tilldelat ett värde som lagras enlig 0.123451234512345 · 103 (15 signifikanta siffror) 16 15 Flyttalslagring mer exakt • Tecken (+/-) - 0 betyder positivt - 1 negativt • Exponenten - Högsta och lägsta exponenten reserverade för speciella tal. - För att klara positiva och negativa har man en bias som adderas till exponenten • Mantissa - Ledande 1:an implicit • 1.Mantissa*2(Exponent-Bias) Tecken Exponent Mantissa Exempel 12.0 Bias float 1 [31] 8 [30-23] 23 [22-00] 127 double 1 [63] 11 [62-52] 52 [51-00] 1023 • • • • • 12 binärt 1100 = 1.100*23 Teckenbit 0 Exponent 127+3=130=>10000010 Mantissa 10000000000000000000000 Totalt: 01000001 01000000 00000000 00000000 Exempel -0.125 • • • • • 0.125 binärt 0.001 = 1.0*2-3 Teckenbit 1 Exponent 127+-3=124=>01111100 Mantissa 00000000000000000000000 Totalt: 10111110 00000000 00000000 00000000 Overflow för float • Det finns 5 talområden där float variabler inte kan hantera normalt: 1. Negativa tal mindre än -(2-2-23) $ 2127 (negative overflow) 2. Negativa tal större än -2-149 (negative underflow) 3. Noll 4. Positiva tal mindre än 2-149 (positive underflow) 5. Positiva tal större än (2-2-23) $ 2127 (positive overflow) 0 Hanteras av ett tal där exponent och mantissa båda är 0 Finns också +- Infinity (Inf) och NotANumber (NaN) • • Intern talrepresentation Utskrift från exemplet ... 9.600000 • Interna talrepresentationen påverkar • noggrannheten Tex blir representationen av 0.1 inte exakt som flyttalen lagras #include <stdio.h> int main(void) { double x; for(x=0;x!=10;x+=0.1) printf("%f\n",x); return 0; } 9.800000 9.900000 10.000000 10.100000 10.200000 10.300000 ... • Loopen avslutas alltså inte då x blir 10. Detta pga att det resultatet inte blir exakt 10 i datorns interna representation. 21 22 Logiska bitvisa binära operationer Logiska bitvisa binära • Tabellen visar and (&), exclusive or (ˆ) och inclusive or (|) på 1-bits fält. a# b# a & b# a ˆ b# a | b 0" 0" 9.700000 0" 0" 0 1" 0" 0" 1" 1 0" 1" 0" 1" 1 1" 1" 1" 0" 1 23 Uttryck# Representation# Värde a" 00000001 01001101" 333 b" 11111100 11110111" -777 a & b" 00000000 01000101" 69 a ˆ b# 11111101 10111010# -582 a | b" 11111101 11111111" -513 24 Shiftoperatorer • De två operatorerna till shiftoperatorerna måste vara av heltalstyp. • Uttrycket expr1 << expr2 # innebär att bitrepresentationen i expr1 shiftas expr2 steg till vänster. int d=1076; 1076 d << 1; 2152 d << 3; 8608 d << 29; -2147483648 d << 32; 0 00000000 00000000 00000000 10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000100 00001000 00100001 00000000 00000000 00110100 01101000 10100000 00000000 00000000 • Vid vänstershift fylls 0:or på från höger Exempel void bit_print(unsigned in) { unsigned mask=1<<8*sizeof(in)-1; while(mask) { printf("%d",mask&in?1:0); mask=mask>>1; } } int main(void) { bit_print(123); printf("\n"); return 0; } 00000000 00000000 00000000 01111011 25 26 Bit fields • • Bit fields Ett annat sätt att komma åt enskilda bitar Man kan ange hur många bitar en del i en struct ska ta struct bit_field_test { /* 4 bitars fält */ unsigned field1 :4; /* ej namngivet 3 bits fält kan användas för att flytta efter efterföljande*/ unsigned :3; /* enbits signade fält kan bara vara 0 eller -1 */ signed field2 :1; /* med delar av storlek 0 flyttar vi om efterföljande till nästa ordstart */ unsigned :0; unsigned field3 :6; }; • Nackdelar • • C ger ingen garanti för ordningen på delarna inom ett maskinord => att koden kan bli plattforms och till och med kompilatorberoende Vissa kompilatorer genererar ineffektiv kod för bitfält