Föreläsning 8: Aritmetik och stora heltal

Relevanta dokument
Föreläsning 8: Aritmetik och stora heltal

Föreläsning 8: Aritmetik I

Föreläsning 9: Talteori

Datoraritmetik. Från labben. Från labben. Några exempel

IE1205 Digital Design: F6 : Digital aritmetik 2

Digital- och datorteknik

Föreläsning 9: Talteori

n Kap 4.1, 4.2, (4.3), 4.4, 4.5 n Numerisk beräkning av derivata med n Felen kan t ex vara avrundningsfel eller mätfel n Felet kan mätas

Teknisk Beräkningsvetenskap I Tema 1: Avrundning och populationsmodellering

Föreläsning 5: Grafer Del 1

Föreläsningsanteckningar F6

Maskinorienterad Programmering /2011. Maskinorienterad Programmering 2010/11. Maskinnära programmering C och assemblerspråk

7 november 2014 Sida 1 / 21

Lösningsanvisningar till de icke obligatoriska workoutuppgifterna

Datorsystemteknik DVG A03 Föreläsning 3

Språket Python - Del 1 Grundkurs i programmering med Python

Algoritmer, datastrukturer och komplexitet

Dagens föreläsning. Repetition. Repetition - Programmering i C. Repetition - Vad C består av. Repetition Ett första C-program

F2 Datarepresentation talbaser, dataformat och teckenkodning EDAA05 Datorer i system! Roger Henriksson!

I Skapa Hej.java och skriv programmet. I Kompilera med javac Hej.java. I Rätta fel och repetera tills du lyckas kompilera ditt program

Objektorienterad Programmering (TDDC77)

Data, typ, selektion, iteration

Programmeringsteknik I

översiktskurs (5DV031)

Algoritmer, datastrukturer och komplexitet

IE1204 Digital Design

Enkla datatyper minne

ÖH kod. ( en variant av koden används i dag till butikernas streck-kod ) William Sandqvist

Introduktion till Datalogi DD1339. Föreläsning 2 22 sept 2014

6. Ge korta beskrivningar av följande begrepp a) texteditor b) kompilator c) länkare d) interpretator e) korskompilator f) formatterare ( pretty-print

Algoritmer, datastrukturer och komplexitet

Objektorienterad Programmering (TDDC77)

Datastrukturer. Erik Forslin. Rum 1445, plan 4 på Nada

Datatyper och kontrollstrukturer. Skansholm: Kapitel 2) De åtta primitiva typerna. Typ Innehåll Defaultvärde Storlek

Fel- och störningsanalys

a = a a a a a a ± ± ± ±500

TDDC77 Objektorienterad Programmering

Feluppskattning och räknenoggrannhet

Lösningsförslag Tentamen i Beräkningsvetenskap I, 5.0 hp,

Kapitel 2. Feluppskattning och räknenoggrannhet

Binär addition papper och penna metod

Fel- och störningsanalys

Programmera i C Varför programmera i C när det finns språk som Simula och Pascal??

Digitalitet. Kontinuerlig. Direkt proportionerlig mot källan. Ex. sprittermometer. Elektrisk signal som representerar ljud.

Föreläsning 3. Iteration while-satsen

Digital- och datorteknik

Iteration while-satsen

Grunderna i C++ T A. Skapad av Matz Johansson BergströmLIMY

Alla datorprogram har en sak gemensam; alla processerar indata för att producera något slags resultat, utdata.

Loopar och datatyper. Föreläsning 3

Algoritmanalys. Inledning. Informationsteknologi Malin Källén, Tom Smedsaas 1 september 2016

Digital- och datorteknik

F2 Datarepresentation talbaser, dataformat och teckenkodning

Programmeringsteknik med C och Matlab

Föreläsning 3: Dekomposition. Dekomposition

Talrepresentation. Ett tal kan representeras binärt på många sätt. De vanligaste taltyperna som skall representeras är:

Loopar och datatyper. Föreläsning 3

Maskinorienterad programmering. Kompendium: Aritmetik för HC12 Roger Johansson, 2013

Programmering i C++ En manual för kursen Datavetenskaplig introduktionskurs 5p

Föreläsning 1: Dekomposition, giriga algoritmer och dynamisk programmering

Förenklad förklaring i anslutning till kompedieavsnitten 6.3 och 6.4

Dagens föreläsning. Repetition. Repetition - Programmering i C. Repetition - Vad C består av. Repetition Ett första C-program

n (log n) Division Analysera skolboksalgoritmen för division (trappdivision). Använd bitkostnad.

Introduktion till programmering SMD180. Föreläsning 9: Tupler

GRUNDER I VHDL. Innehåll. Komponentmodell Kodmodell Entity Architecture Identifierare och objekt Operationer för jämförelse

Datorsystem. Övningshäfte. Senast uppdaterad: 22 oktober 2012 Version 1.0d

Föreläsning 2 Datastrukturer (DAT037)

Objektorienterad programmering Föreläsning 4

Per Holm Lågnivåprogrammering 2014/15 24 / 177. int och double = = 2, 147, 483, 647

Variabler, värden och typer

DD1314 Programmeringsteknik

Variabler och konstanter

Datoraritmetik. Binär addition papper och penna metod. Binär subtraktion papper och penna metod. Binär multiplikation papper och penna metod

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 5 Jonas Lindgren, Institutionen för Datavetenskap, LiU

Datalogi I, grundkurs med Java 10p, 2D4112, Fiktiv tentamen, svar och lösningar och extra kommentarer till vissa uppgifter 1a) Dividera förs

TDDI16 Datastrukturer och algoritmer. Algoritmanalys

Klassdeklaration. Metoddeklaration. Parameteröverföring

Algoritmer och datastrukturer H I HÅKAN S T R Ö M B E R G N I C K L A S B R A N D E F E L T

Sökning och sortering

1/15/2013. DD1310/DD1314/DA3009 Programmeringsteknik. Lärandemål... Vilka läser kursen? ...fler lärandemål VARFÖR? Föreläsning 1

Föreläsning 2 Programmeringsteknik och C DD1316. Mikael Djurfeldt

LAB 1. FELANALYS. 1 Inledning. 2 Flyttal. 1.1 Innehåll. 2.1 Avrundningsenheten, µ, och maskinepsilon, ε M

DD1310/DD1314/DA3009 Programmeringsteknik LÄRANDEMÅL... Vilka läser kursen? ...FLER LÄRANDEMÅL. Föreläsning 1

Sammanfattninga av kursens block inför tentan

Programmering i C. Vad är C? Målsättning. Litteratur. Jämförelse med Java. Exempel : Ett program som skriver ut texten Hello, world

Föreläsning 5: Dynamisk programmering

Variabler, värden och typer

SVAR TILL TENTAMEN I DATORSYSTEM, HT2013

Användarhandledning Version 1.2

Lösningsanvisningar till de icke obligatoriska workoutuppgifterna

1 Datorn som miniräknare. 1.1 Räkneoperationer. 1.2 Variabler

732G Linköpings universitet 732G11. Johan Jernlås. Översikt. Repetition. Felsökning. Datatyper. Referenstyper. Metoder / funktioner

Rekursion och induktion för algoritmkonstruktion

Flyttal kan också hantera vanliga tal som både 16- och 32-bitars dataregister hanterar.

Introduktion till algoritmer - Lektion 1 Matematikgymnasiet, Läsåret Lektion 1

F5 Selektion och iteration. ID1004 Objektorienterad programmering Fredrik Kilander

TDDC77 Objektorienterad Programmering

Föreläsning 2 Programmeringsteknik och Matlab DD1312. Programspråk. Utskrift på skärmen

Lösning av några vanliga rekurrensekvationer

Föreläsning 3: Typomvandling, villkor och val, samt textsträngar

Transkript:

DD2458, Problemlösning och programmering under press Föreläsning 8: Aritmetik och stora heltal Datum: 2007-11-06 Skribent(er): Martin Tittenberger, Patrik Lilja Föreläsare: Per Austrin Denna föreläsning handlade om beräkningar med flyttal och stora heltal. 1 Flyttalsaritmetik Låt oss betrakta två exempel där flyttal inte beter sig som man tror. Exempel 1: Avrundning double x = 0.29; int y = (int) (100 * x); printf("%d", y); Utdata från programmet ovan blir 28 istället för 29. Exempel 2: Jämförelse for (double x = 0.0; x!= 1.0; x += 0.1) printf("hello World\n"); Loopen kommer att köras oändligt många gånger eftersom termineringsvillkoret aldrig uppfylls. 1.1 Flyttalsrepresentation Orsaken till att de märkliga fenomenen uppstår i exemplen ovan är att man i allmänhet inte kan representera reella tal exakt med ändligt mycket minne. I exemplen används primitiva datatyper vars precision är begränsad. Vi skall titta närmare på hur flyttal representeras i minnet. 1.1.1 IEEE Floating Point Representation Ett flyttal x representeras på följande sätt enligt IEEE standarden: x = S M 2 E, där: S = Teckenbit {0, 1} M = Mantissa (siffrorna i talet) E = Exponent (storleken på talet) 1

2 DD2458 Popup HT 2007 Typ Teckenbit Mantissa Exponent Storlek float 1 24 8 32 double 1 53 11 64 long double 1 1 113 15 128 2 Tabell 1: Antal bitar för S, M och E för olika flyttalstyper. 1.1.2 Flyttalstyper Som man kan notera i tabell 1 är summan av antalet bitar för de respektive typerna ett större än storleken (totala antalet bitar). Detta beror på att flyttal lagras i en normaliserad form där den mest signifikanta biten i mantissan alltid är satt. Därför behöver inte denna bit lagras. Om den mest signifikanta biten inte skulle vara satt så kan man istället representera talet som S (2 M) 2 E 1. 1.1.3 En närmare titt på double Ett flyttal x av typen double representeras på följande sätt: x =( 1) S (1 + M 2 52 ) 2 E 1023 där S {0, 1}, 0 M<2 52, 1 E<2 11 1. Värdena E =0och E =2 11 1 är reserverade för speciella tal. En double där E =0representerar talet: ( 1) s (M 2 52 ) 2 1023 Notera att om M =0får vi precis 0.Endouble där E =2 11 1 kan representera oändligheten eller NaN 3,setabell2. Exponent Mantissa Betydelse 0 0 ±0 (beror på S) 0 0 Ej normaliserat tal 2047 0 ± (beror på S) 2047 0 NaN (Not a Number) Tabell 2: Reserverade tal. För att erhålla samt NaN i C++ utan att få varken kompileringsvarningar eller fel så behöver man först inkludera <numeric> och sedan anropa funktionerna: std::numeric_limits<double>::infinity() std::numeric_limits<double>::quiet_nan() I Java är motsvarande värden definierade som konstanter i klassen Double och kan kommas åt på följande sätt: Double.NEGATIVE_INFINITY Double.POSITIVE_INFINITY Double.NaN 1 Datatypen finns ej i Java. 2 Storleken varierar mellan 80 och 128 bitar beroende på arkitektur. 3 Resultatet av att någon operation misslyckades. Ex. 1, 0.0/0.0,

Aritmetik och stora heltal 3 1.2 Varför blir det fel? Vi skall nu redogöra mer ingående för varför de märkliga fenomenen uppstod i de två första exemplen samt presentera ett par olika lösningsförslag. Exempel 1 Talet 0.29 kan inte representerasexakt med en double. Datornlagrardå istället den double som ligger närmast 0.29, vilken råkar vara 0x128F 5C28F 5C28F 2 54 och som har det ungefärliga värdet 0.28999999999999998. När talet sedan multipliceras med 100 och trunkeras till ett heltal erhåller vi resultatet 28. Lösning Läs in talet som <int>.<int>. Kan dock bli knepigt att kunna skilja på tal som t.ex. 5.1 och 5.01. Avrunda till närmsta heltal. y = (int) (x * 100 + 0.5) Detta fungerar så länge x inte är för stort (men i sådant fall så behöver man ändå en större datatyp för y). Exempel 2 Talet 0.1 kan inte heller representeras exakt med en double. Men det kan däremot 1. Detta betyder att efter 10 iterationer i for-loopen så kommer inte variabeln x att anta exakt värdet 1 (men nästan). Termineringskriteriet kommer alltså aldrig att uppfyllas. Lösning Använd ej strikt jämförelse (==) för att kontrollera likhet mellan två flyttal a och b, tya och b är sällan exakt lika. I detta fall lämpar det sig bättre att undersöka om talen är väldigt nära varandra. Två metoder man kan tillämpa för att jämföra flyttal på är: Absolutfel: Vi definierar a och b som lika i absolut bemärkelse: och a är mindre än b: a abs = b om a b <ɛ a abs <bom a abs b och a<b Relativfel: Vi definierar a och b som lika i relativ bemärkelse: a rel = b om a b <ɛ ( a + b ) och a är mindre än b: a rel <bom a rel b och a<b

4 DD2458 Popup HT 2007 Absolutfel fungerar dåligt för mycket stora tal eftersom differensen mellan talen kan vara stor trots att den relativt sett är obetydlig. Relativfel fungerar dåligt för små tal av motsvarande skäl. Vill man vara helt säker så kan man använda båda metoder. Då gäller: a komb = b om a abs = b eller a rel = b a komb < b om a komb b och a<b Vilket värde man skall välja på ɛ varierar från fall till fall, men ett värde mellan 10 7 och 10 13 räcker för de flesta tillämpningar. 1.3 float vs. double I de flesta tillämpningar där man behöver använda flyttal så bör man välja double. Det ger betydligt högre precision än float och har väsentligen samma prestanda. float kan dock vara användbar om man har ont om minne, eller om avrundningsfel inte har någon betydelse, som t.ex. i datorgrafiksammanhang. Om man behöver godtycklig precision så kan man använda sig av biblioteket GMP 4 för C++ eller klassen BigInteger ijava. 1.4 Exempel på när flyttal är att föredra framför heltal. Finn y = 4 x, 1 x 10 40 givet att y är ett heltal. Observera att x är för stort för att kunna lagras i en heltalstyp. Lösning 1. Läs in x som en double för erhålla approximationen X x (1 ± ɛ) där ɛ 10 15. 2. Låt Y = pow(x, 0.25) vara en approximation av y. 3. Låt svaret vara Y avrundat till närmaste heltal. 1.4.1 Analys av precision Låt oss analysera hur stort fel Y kan ha. Y = pow(x, 0.25) (1 ± ɛ) X 1 4 =(1± ɛ) e ln(x)/4 (1 ± ɛ) e ln(x) 4 (1±ɛ) ±ɛ ln(y) =(1± ɛ) y e (1 ± ɛ) (1 ± ɛ ln(y)) y y ± y ɛ (1 ± ln(y)) 4 GNU Multiple Precision Arithmetic Library, http://gmplib.org/

Aritmetik och stora heltal 5 I tredje sista steget utnyttjade vi likheten ln(x) 4 =ln(y), och i näst sista steget utnyttjade vi att e ±δ 1 ± δ, för små värden på δ. Vi får slutligen ett fel i vår beräkning som är Y y y ɛ (1 + ln(y)) 2 10 4 0.5, vilket är vad som krävs för att få korrekt svar efter avrundning. 1.5 Mer information Mer utförlig information om flyttalshantering finns att läsa i följande artikel: http://docs.sun.com/source/806-3568/ncg_goldberg.html 2 Heltalsaritmetik 2.1 Floor och ceil Givet x R definieras: x = floor(x) som det största heltal mindre än eller lika med x. x = ceil(x) som det minsta heltal större än eller lika med x. x x x 5 5 6 5.3 5 6 0.7 1 0 Tabell 3: Exempel på floor och ceil 2.1.1 Operationer Givet x R och n, m Z gäller följande: 2.1.2 Att beräkna n m och n m x = n n x<n+1 x = n n 1 <x n x = x x = x x ± n = x ±n x ± n = x ±n n n + m 1 = för m>0 m m Det enklaste sättet att beräkna n m och n m ärattförstberäkna n m som en double och sedan använda sig av floor och ceil. Detta kommer att fungera så länge inte talen blir väldigt stora då vi riskerar att få avrundningsfel. Dessa beräkningar kan göras på ett mer precist sätt. Idéen är att använda identiteterna ovan till att reducera alla fall till n m med n, m > 0, vilket ju precis motsvaras av heltalsdivision.

6 DD2458 Popup HT 2007 Algoritm 1: Beräkning av n m,därn, m Z Floor-Fraction(n, m) (1) if m<0 (2) return Floor-Fraction( n, m) (3) else if n<0 (4) return Ceil-Fraction( n, m) (5) else (6) return n/m Algoritm 2: Beräkning av n m,därn, m Z Ceil-Fraction(n, m) (1) if m>0 (2) return Floor-Fraction(n + m 1, m) (3) else (4) return Floor-Fraction( n m 1, m) 2.1.3 Exempel på tillämpning Kattisproblemet Rare Easy Problem 5 kan lösas på ett enkelt sätt med hjälp av floor och ceil. Problemet går ut på att hitta N givet K = N M, därm är N med sista siffran borttagen. Notera att M = N/10. Vi vill alltså bestämma N så att N N/10 = K. K = N N/10 = N + N/10 = 9N/10 K 1 < 9N/10 K 10(K 1) < 9N 10K 10(K 1) + 1 9N 10K 10K/9 1 N 10K/9 10K/9 1 N 10K/9 Där vi använder definitionen av ceil, från 2.1.1, vid övergången från likhet till olikhet. Om K ärdelbartmed9 så kommer vi att få lösningarna 10K/9 och 10K/9 1, annars kommer lösningen att vara 10K/9. 2.2 Stora heltal Ibland räcker inte de primitiva datatyperna till. Exempelvis vore kryptosystem som RSA enkla att knäcka om man bara använde sig av 64-bitars nycklar. I verkliga tillämpningar använder man sig typiskt av färdiga bibliotek som GMP eller 5 http://kattis.csc.kth.se/problem?id=easy

Aritmetik och stora heltal 7 BigInteger. Här ska vi dock titta på hur man själv kan skapa enkla motsvarigheter vilket man kan vara tvingad till i problemlösningssammanhang. 2.2.1 Representation Vi kan skriva ett tal x i någon bas b som: x = x n 1 b n 1 + x n 2 b n 2 + + x 2 b 2 + x 1 b + x 0 där 0 x i <b. Koefficienterna lagras exempelvis i en vektor. 2.2.2 Hur väljer vi b? b =2 k,t.ex.2 32 eller 2 64 Effektivt eftersom man utnyttjar minnesutrymmet väl vilket innebär att det blir få x i och därmed få beräkningar. Att det dessutom är datorns interna representation gör att division- och moduloberäkningarna i nedanstående algoritmer kan implementeras effektivt med shift- ochand-operationer. En nackdel är att en inläsning och utskrift i bas 10 blir jobbigt. b =10 Enkelt med inläsning, men ineffektivt eftersom b är så litet, vilket innebär att det blir det många x i och därmed görs fler beräkningar och det krävs mer minne. b =10 d Vid tillfällen då man behöver skriva ihop en lösning snabbt så är detta en bra kompromiss. In- och utläsning blir enkelt och samtidigt utnyttjas minnesutrymmet ganska väl. För att undvika overflow vid multiplikation så bör d väljas så att 10 2d = b 2 får plats i den primitiva datatyp man valt för vektorn [x i ]. Om man t.ex. använder en 64-bitars heltalstyp så är d =9ett bra val. 2.2.3 Operationer Vi antar att talen x, y och z är representerade som ovan i basen b. Vitänkerossatt x i =0om i> x, där x betecknar storleken på x:s vektor, samma sak gäller för y och z. Notera att dessa algoritmer är samma som man lärde sig i grundskolan. Algoritm 3: Addition, x + y Add(x, y) (1) carry 0 (2) n max( x, y ) (3) for i 0 to n 1 (4) tmp x i + y i + carry (5) z i tmp mod b (6) carry tmp/b (7) z n carry (8) return z

8 DD2458 Popup HT 2007 Algoritm 4: Subtraktion, x y Sub(x, y) (1) if x<y (2) return Sub(y,x) (3) borrow 0 (4) n max( x, y ) (5) for i 0 to n 1 (6) tmp x i y i borrow (7) z i tmp mod b (8) if tmp < 0 (9) borrow 1 (10) else (11) borrow 0 (12) return z Algoritm 5: Multiplikation, x y Mul(x, y) (1) z 0 (2) n x (3) m y (4) for i 0 to n 1 (5) for j 0 to m 1 (6) z i+j z i+j + x i y j (7) carry 0 (8) l z (9) for j 0 to l 1 (10) z j z j + carry (11) carry z j /b (12) z j = z j mod b (13) z l carry (14) return z För varje varv i loopen gäller att: z i+j = z i+j från föregående varv + x i y j + minnessiffror b 1+(b 1) 2 + b 1 = b 2 1 Det betyder att om vi väljer b så att b 2 1 ryms i den datatyp som används så löper vi ingen risk för overflow. Algoritmen har tidskomplexitet Θ(n 2 ), det finns dock betydligt snabbare algoritmer för multiplikation av stora tal. 6 6 Karatsuba Θ(n log 2 3 ), Fast-Fourier-Transform O(n log n log log n)

Aritmetik och stora heltal 9 Algoritm 6: Division (med små nämnare) Input: Heltal x och a, dära<b Output: Tupel ( x/a,x mod a) Div(x, a) (1) r 0 (2) n x (3) for i n 1 to 0 (4) tmp b r + x i (5) z i tmp/a (6) r tmp mod a (7) return (z,r) För att utföra division med stora nämnare krävs en betydligt krångligare algoritm. 2.2.4 Exponentiering Antag att vi vill beräkna x e för några heltal x och e. Den naiva ansatsen är att göra e stycken multiplikationer, vilket kan ta lång tid om e är stort. Det går att göra betydligt snabbare. Vi gör observationen att x e = x e mod 2 x 2 e 2 och utnyttjar det till att skapa en algoritm. Algoritm 7: Beräkning av x e genom upprepad kvadrering Square-and-Multiply(x, e) (1) z 1 (2) while e 0 (3) if e mod 2 = 1 (4) z z x (5) x x x (6) e e/2 (7) return z Eftersom e halveras i varje steg så kommer vi att göra O(log e) multiplikationer.