Många beräkningar är approximationer Ändlig aritmetik • 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 25 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 26 27 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 28 • 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). 29 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? 30 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, . . . ). 32 33 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 34 35 Addition Ex1 (i en byte för enkelhetens skull) 3+(-2)=1 1 1 1 1 1 1 1 Addition Ex2 127 + 1 = -128 0 0 0 0 0 0 1 1 + 1 1 1 1 1 1 1 0 = 0 0 0 0 0 0 0 1 Övriga heltalstyper • short lagras oftast med 2 byte (vanligen mindre intervall än int). • long lagras oftast med 4 eller 8 byte. (vanligen större intervall än int). • unsigned framför en heltalstyp (ex. unsigned int) innebär att enbart positiva tal kan lagras. Detta innebär också att intervallet för tal (positiva) som kan lagras fördubblas. 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 Typstorlek, sizeof • Operatorn sizeof används för att veta hur många bytes som krävs för att lagra ett objekt. • Objekt kan vara en datatyp (float), eller ett uttryck (a+b). sizeof(int) sizeof(a+b) • sizeof returnerar ett heltal som anger hur många bytes som krävs för lagringen. • C är flexibelt när det gäller storlekarna på datatyper vilket kan leda till dålig portabilitet av kod. Användandet av sizeof kan delvis undvika detta problem. 38 39 Lagring Konvertering • Följande gäller alltid på alla system. • • sizeof(char) == 1 sizeof(unsigned) == sizeof(signed) == sizeof(int) sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long) • ANCI C specificerar också att sizeof(int) >= 2 sizeof(long) >= 4 40 • Ett uttryck som x+y har både ett värde och en datatyp. Om både x och y är av typen int, så får x+y typen int. Däremot, om både x och y är av typen short, så kommer x+y att få typen int. Detta på grund av att short alltid konverteras till int. En char eller short (signed eller unsigned) kan användas där en int eller unsigned int förväntas. Ex. Om en funktion tar en int som argument, kan man skicka en char istället. Om däremot funktionen returnerar en int, så bör man inte ta emot det i en char. 41 • • • Aritmetiska konverteringar Explicita konverteringar Om operanderna till en binär operator är av olika typ så kan en av dom konverteras. Anta att i är int och f är float. I uttrycket i+f så konverteras i till en float och hela uttrycket får typen float. Vid tilldelningar kan också konvertering ske. Om vi antar att i är av typen int och d är av typen double, kommer värdet av d = i att konverteras till double och hela uttrycket bli double. En utökning av en variabel, som sker i fallet med d = i går ofta bra men däremot i = d kan orsaka problem. Decimaldelen av d kommer att försvinna och i kommer att tilldelas heltalsdelen. • Explicita konverteringar (eng. casts) låter programmeraren byta typ på ett uttryck. Om vi antar att i är av typen int så kommer (double)i att konvertera värdet av i så att uttrycket har typen double. • Variabeln i påverkas inte av konverteringen utan är fortfarande av typen int 42 43 Flyttal Exempel • 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) 45 44 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 • • Intern talrepresentation • 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; } Utskrift från exemplet ... 9.600000 9.700000 9.800000 9.900000 10.000000 10.100000 10.200000 10.300000 ... 50 51 Logiska bitvisa binära 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" 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) 0" 0" 0 1" 0" 0" 1" 1 0" 1" 0" 1" 1 1" 1" 1" 0" 1 52 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 53 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 00000000 00000000 00000100 00110100 54 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 55