Ändlig aritmetik Exempel Avrundningsregler Olika typer av fel Heltal

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