Ändlig aritmetik Exempel Avrundningsregler Olika typer av fel Heltal

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