252-0027 Einführung in die Programmierung I 10.0

Werbung
252-0027
EinführungindieProgrammierungI
10.0Systema=schesProgrammieren
ThomasR.Gross
DepartmentInforma=k
ETHZürich
Copyright(c)Pearson2013andThomasGross2016
Allrightsreserved.
Uebersicht
!  10.0Beispiel
!  10.1DarstellungvonVariablenundObjekten
!  10.1AsserIons
!  10.2Pre/PostCondiIons(fürStatement)
!  10.3Pre/PostCondiIons(fürFolgenvonStatements)
2
RaIonaleZahlen
!  BeispieleinersinnvollenKlasse
!  Idee:KlasseRational fürdieDarstellungvonraIonalen
Zahlen
!  ReelleZahldiealsVerhältniszweierganzerZahlendargestelltwird
!  Warum:Diedouble DarstellungistnureineApproximaIon
double x = (1.0 / 2.0) + (1.0/3.0) + (1.0/6.0);
System.out.println(x);
RaIonaleZahlen
!  BeispieleinersinnvollenKlasse
!  Idee:KlasseRational fürdieDarstellungvonraIonalen
Zahlen
!  ReelleZahldiealsVerhältniszweierganzerZahlendargestelltwird
!  Warum:Diedouble DarstellungistnureineApproximaIon
double x = (1.0 / 2.0) + (1.0/3.0) + (1.0/6.0);
System.out.println(x);
Output: 0.9999999999999999
RaIonaleZahlen
!  ExakteDarstellung
!  0.1==1/10
!  KlasseRaIonalunterstütztdieüblichenarithmeIschen
OperaIonen
Addition:"
a
c
+
=
b
d
ad+bc
bd
Multiplication:"
a x c
=
b
d
Subtraction:"
a
c
–
=
b
d
ad–bc
bd
Division:"
ad
a .. c
=
bc
b
d
ac
bd
5
ImplementaIonvonRaIonal
!  VorschauaufdienächstenSeiten
!  VerschiedeneKonstruktoren
!  Overloading
!  Default:0,einArgument:ganzeZahl;zweiArgumente:QuoIent
!  DieKonstruktorenstellensicherdassZählerundNennerauf
diekleinstmöglichenWerte“gekürzt”werden
!  DasichdieInstanzenderKlassenieändernbleibtdieseEigenschae
bestehen
ImplementaIonvonRational
!  DieOperaIonen(add,subtract,mulIply,unddivide)fürdie
vierGrundoperaIonenverwendendiedot-NotaIon–
!  EinerderOperandenistderimpliziteParameter,deranderederinder
DefiniIonaufgeführteParameter
!  AufdenimplizitenParameterwirddurchthis zugegriffen.
KlasseRaIonal
/**
* The Rational class is used to represent rational numbers, which
* are defined to be the quotient of two integers.
*/
public class Rational {
/** Creates a new Rational initialized to zero. */
public Rational() {
this(0);
}
/**
* Creates a new Rational from the integer argument.
* @param n The initial value
*/
public Rational(int n) {
this(n, 1);
}
skipcode
KlasseRational
/**
/**
*
a newclass
Rational
withto
the
value x /
y.
* Creates
The Rational
is used
represent
rational
numbers, which
*
@param
x
The
numerator
of
the
rational
number
* are defined to be the quotient of two integers.
*
*/@param y The denominator of the rational number
*/
public class Rational {
public Rational(int x, int y) {
int g =
Math.abs(y));
/** Creates
a gcd(Math.abs(x),
new Rational initialized
to zero. */
num
=
x
/
g;
public Rational() {
den
= Math.abs(y) / g;
this(0);
if
(y
< 0) num = -num;
}
}
/**
/**
* Creates a new Rational from the integer argument.
*
the
number
r to this one and returns the sum.
* Adds
@param
n rational
The initial
value
*
@param
r
The
rational
number
to be added
*/
* @return
The sum of the
number and r
public Rational(int
n) current
{
*/
this(n, 1);
public
Rational add(Rational r) {
}
return new Rational(this.num * r.den + r.num * this.den,
this.den * r.den);
}
KlasseRational
/**
* Subtracts
Creates a the
new rational
Rational number
with the
r from
valuethis
x / one.
y.
* @param r
x The rational
numeratornumber
of theto
rational
be subtracted
number
* @return
@param yThe
Theresult
denominator
of subtracting
of the rational
r from the
number
current number
*/
public Rational
Rational(int
subtract(Rational
x, int y) {
r) {
return
int g =new
gcd(Math.abs(x),
Rational(this.num
Math.abs(y));
* r.den - r.num * this.den,
num = x / g;
this.den * r.den);
} den = Math.abs(y) / g;
if (y < 0) num = -num;
/**}
* Multiplies this number by the rational number r.
/**
* @param r The rational number used as a multiplier
* @return
Adds theThe
rational
resultnumber
of multiplying
r to thisthe
onecurrent
and returns
number
the
bysum.
r
*/
* @param r The rational number to be added
* public
@returnRational
The sum multiply(Rational
of the current number
r) {and r
*/
return new Rational(this.num * r.num, this.den * r.den);
}
public Rational add(Rational r) {
return new Rational(this.num * r.den + r.num * this.den,
this.den * r.den);
}
skipcode
KlasseRational
/**
* Divides
Subtracts
this
thenumber
rational
by the
number
rational
r fromnumber
this one.
r.
* @param r The rational number used
to beas
subtracted
a divisor
* @return The result of dividing
subtracting
thercurrent
from the
number
current
by r
number
*/
public Rational divide(Rational
subtract(Rational
r)r)
{ {
return new Rational(this.num * r.den,
r.den -this.den
r.num * *
this.den,
r.num);
}
this.den * r.den);
}
/**
/**
* Creates a string representation of this rational number.
* @return
Multiplies
Thethis
string
number
representation
by the rational
of this
number
rational
r.
number
*/
* @param r The rational number used as a multiplier
* public
@returnString
The result
toString()
of multiplying
{
the current number by r
*/
if (den == 1) {
publicreturn
Rational
"" +
multiply(Rational
num;
r) {
}
return
else {
new Rational(this.num * r.num, this.den * r.den);
}
return num + "/" + den;
}
skipcode
KlasseRational
/**
* Calculates
Divides this
the
number
greatest
by the
common
rational
divisor
number
usingr.Euclid's algorithm.
* @param x
r First
The rational
integernumber used as a divisor
* @param
@returnyThe
Second
result
integer
of dividing the current number by r
*
*/@return The greatest common divisor of x and y
*/public Rational divide(Rational r) {
private
return
int
new
gcd(int
Rational(this.num
x, int y) { * r.den, this.den * r.num);
} int r = x % y;
while (r != 0) {
/**
x = y;
* Creates
y =
a r;
string representation of this rational number.
* @return
r =
The
x %
string
y;
representation of this rational number
*/
}
public
return
String
y; toString() {
} if (den == 1) {
return "" + num;
/* Private
} else
instance
{
variables */
private
return
int num;
num + "/"
/* The
+ den;
numerator of this Rational
*/
private
}
int den;
/* The denominator of this Rational */
}
}
skipcode
SimulaIon
!  WirwollensehenwieeineinfachesProgrammdreiraIonale
Zahlenaddiert
1
2
+
1
3
+
1
6
!  DanachwerfenwireinenBlickhinterdieKulissen
!  DasErgebnisdieserBerechnungsoll(te)exaktsein1sein
!  ImGegensatzzurRechnungmitdouble
public void run() {
Rational
Rationalaa==new
newRational(1,
Rational(1,2);
2);
public Rational
add(Rational
Rational(int
x, int y)r)
{ {
36
5
Rational
Rationalbb==new
newRational(1,
Rational(1,3);
3);
int g = gcd(Math.abs(x), Math.abs(y));
Rational
cc==new
Rational
newRational(1,
Rational(1,
6);
public
x, this.num
int y)6);
{ * r.den + r.num * this.den ,
return
Rational(
num = Rational(int
xnew
/ g;
Rational
sum
==a.add(b).add(c);
Rational
sum
a.add(b).add(c);
int
g
=
gcd(Math.abs(x),
Math.abs(y));
this.den * r.den );
den = Math.abs(y) / g;
System.out.println(a
" "
+ +
" "
+ +
b c
+ +
" "
+ =
" "
+ +
c sum);
+ " = " + sum);
println(a
+/ "g;+ " + +
b +
num
if
(y =< x0)
num = -num;
}}
den = Math.abs(y)
36
6
temporary / g;
}
a
b
c
sum
result= -num;
if (y < 0) num
}
1
1
1
5
this
r 1
2
1 1
6
x 3
y 6
gnum
num 5
1
this
den 6
den1 6
2
3
2
3
x 1
y 6
g 3
num 1
5
den 1
36
5
36
6
36
1
6
TestRational
1/2 + 1/3 + 1/6 = 1
BasedonEricRoberts,The
ArtandScienceofJava
skipsimula9on
Darstellungsfragen
!  Warumergibteigentlich
double x = (1.0 / 2.0) + (1.0/3.0) + (1.0/6.0);
System.out.println(x);
Output: 0.9999999999999999
!  WertemüssenimSpeicherdesComputersdargestelltwerden
!  SpeicherorganisiertalseineGruppevonBits
!  Bit:binarydigit
20
Darstellungsfragen
!  EinBithatzweiZustände:normalerweisemit0und1
bezeichnet
!  Gruppenvon8BitsbildeneinByte
0
0
1
0
1
0
1
0
!  NurzurVereinfachungderImplementaIondesRechners
!  (Ganzeundreelle)ZahlenwerdenineinerFolgevonBytes
gespeichert
!  EineFolgevonBytesheissteinWord.ComputerkönnenoeeinWord
schnellverarbeiten(schnellerals4beliebigeaufeinanderfolgendeBytes)
21
Darstellungsfragen
!  EineganzeZahlwirdoeineinemWordausvierBytes
gespeichert
!  MancheComputerbezeichnenalseinWordalsFolgevon8
Bytes
!  UndspeicherndanneineganzeZahlin64Bits
22
Binärdarstellung
!  WennwirdieBitseinesBytesalsBinärzahlinterpreIerenso
könnenwirineinemByteeineganzeZahldarstellen
!  BinärzahlensindwieDezimalzahlenaberverwendeneine
andereBasis
!  DezimalzahlenBasis==10
!  DasGewichteinerZifferistdas10-fachedesGewichtsderZiffer
zurRechten
!  BinärzahlenBasis==2
!  DasGewichteinerZifferistdasDoppeltedesGewichtsderZiffer
zurRechten
Binärdarstellung
0
0
1
0
1
0
1
0
0×1
0
1×2
2
0×4
0
1×8
8
0×16
0
1×32
32
0×64
0
0×128
0
42
DarstellungeneinerZahl
!  DieBinärdarstellung00101010istäquivalentzur
Dezimaldarstellung42
!  WenndieBasiswichIgist,dannwirdsiealsIefgestellt
!  001010102=4210
!  AberesistimmerdieselbeZahl
!  ZahlenhabenkeineBasis,nurDarstellungen
25
Oktal-undHexadezimalschreibweise
!  8Bitssindmühsamzuschreiben
!  Leichtetwaszuübersehen(00101010oder00101011)
!  InformaIkerverwendendaheroedieOktalschreibweise
(oderdieHexadezimalschreibweise)
!  Oktal:Ziffern0…7
!  Hexadezimal:Ziffern0….9ABCDEF
26
Oktal-undHexadezimalschreibweise
!  DieZahl00101010inOktal-undHexadezimalschreibweise
octal
5
hexadecimal
2
2
2
5
x
x
1
8
2
40
42
A
10 x 1
02 x 16
10
32
42
!  DerVorteildieserDarstellungenistdasssieleichtindie
Binärdarstellungumgewandeltwerdenkönnen
!  JedeZifferkanneinzelnumgewandeltwerden
28
Uebung:Zahlendarstellungen
!  WasistdieDezimaldarstellungfürdieseZahlen
100012
AD16
1778
17
1
0
0
0
1
1
0
0
0
1
x
x
x
x
x
1
2
4
8
16
1
0
0
0
1
17
Uebung:Zahlendarstellungen
!  WasistdieDezimaldarstellungfürdieseZahlen
100012
AD16
1778
127
1
7
7
7
7
1
x
x
x
1
8
64
7
56
64
127
Uebung:Zahlendarstellungen
!  WasistdieDezimaldarstellungfürdieseZahlen
100012
1778
AD16
173
A D
13 x 1
10 x 16
13
160
173
Startjeder.classFile
!  Diessinddieersten16Bitsjeder.classfile
1
1
0
0
1
0
1
0
1
1
1
1
1
1
1
0
!  WasistdieseZahlinHexadezimalnotaIon?
1
1
0
0
1
0
1
0
1
F
CAFE16
1
1
1
1
1
1
0
od–tx1Foo.class
[Linux]
SpeicherundAddressen
•  Jedes Byte im Speicher hat eine Adresse –
eineZahlzwischen0undeinerObergrenze
0000
0004
0001
0008
0002
000C
0003
0010
0004
0014
0005
0018
0006
001C
0007
•  Im Beispiel sind Adressen in HexadezimalnotaIonmit4Stellenangezeigt
•  ImJavaSystemsinddieAdressenunsichtbar
unddasBespielzeigtwillkürlicheWerte
•  IllustraIonen mit Bytes sind unübersichtlich
daher fassen wir 4 Bytes zu einem Wort
zusammen und zeigen immer Wortadressen
(diedannin4-erSchrixenansteigen)
0020
0008
0024
0009
.
.
.
.
.
.
0028
000A
002C
000B
FFD0
FFF4
FFD4
FFF5
FFD8
FFF6
FFDC
FFF7
FFE0
FFF8
FFE4
FFF9
FFE8
FFFA
FFEC
FFFB
FFF0
FFFC
FFF4
FFFD
FFF8
FFFE
FFFC
FFFF
SpeicherplatzfürVariable
!  FüreinedeklarierteVariablemussdasLaufzeitsystem
Speicherplatzfinden
!  DerSpeicherdesComputersistinverschiedeneBereiche
unterteilt
!  Genauer:derTeildesSpeichersdenunserJavaProgrammnutzendarf
!  EinBereichistreserviertfürdieVariablendieimmer
exisiteren(währenddergesamtenLaufzeitdesProgramms)
!  DazugehörtenKonstanten,InformaIonenüberKlassen,etc.
!  DieserBereichheisst“staIcdata”
SpeicherplatzfürVariable
!  ObjektediedurchdennewOperatorerschaffenwerden,
werdenim“heap”(Halde)abgelegt.
!  FürjedeaufgerufeneMethodestelltdasLaufzeitsystemeinen
neuenBereichzurVerfügung
!  Dieserheisst“StackFrame”
!  AlleStackFrameswerdenineinemStackorganisiert
!  Variable,dieineinerMethodedeklariertwurden,findenPlatzimStack
Frame
!  Parameterüberigensauch…
36
staIc
data
heap
stack
0000
staIc
data
0000
heap
!  ManchmalsindStackundHeapso
angeordnet,dasssiegegeneinander
wachsen
!  JedeRegionkannsogrosswiemöglich
werden
stack
FFFF
StackundHeap
!  EineinfachesModelldieserBereichehile,verschiedene
AspektevonJavazuverstehen
!  DaProgrammeoeineinerMethodeVariabledeklarieren,die
aufInstanzenverweisen,müssenwirsowohldenHeapals
auchdenStackimAugebehalten
!  IndenfolgendenFolienzeigenwirlinksdenHeapundrechts
denStack
!  GetrenntdurchLinie
!  Stack-HeapDiagramm
39
StackundHeap
!  WenneineMethodeaufgerufenwird,dannmussdasneue
StackFramegenugPlatzfüralle(lokalen)Variablenhaben
!  WenneineMethodeferIgist,dannkannihrStackFrame
wiederverwendetwerden
!  WenneineObjekInstanzgeschaffenwird,dannbrauchenwir
SpeicherplatzfüralleAxribute(Zustandsvariablen)
!  DazubrauchenwirextraPlatzfürJava-interneZwecke–Overheadden
wirnichtkontrollierenkönnen
40
Verweise(References)aufObjekte
!  FürjedeInstanzhältdasJavaSystemdieAdressederInstanz
fest
!  DieseAdresse(ggf.mitweiterenInformaIonen)wirdineinerVariable
gespeichert(wirsagendazuauch“Referencevariable”–dieVariable
enthältdenVerweis,d.h.dieReference,aufeinObjekt).
!  Nehmenwiran,eineMethodeenthältdieDeklaraIon
Rational r1 = new Rational(1, 2);
fürdie Klasse Rational (wievorhereingeführt)
41
Verweise(References)aufObjekte
!  WenndieDeklaraIon
Rational r1 = new Rational(1, 2);
ausgeführtwird,brauchenwirPlatzfüreineneueRationalInstanz.
!  NehmenwirandiesenfindenwirmitderAdresse1000
42
Verweise(References)aufObjekte
!  WenndieDeklaraIon
Rational r1 = new Rational(1, 2);
ausgeführtwird,brauchenwirPlatzfüreineneueRationalInstanz.
!  NehmenwirandiesenfindenwirmitderAdresse1000
heap
stack
1000
num
den
1
1004
2
1008
r1
1000
FFFC
!  DieVariabler1wirdimStackFramegespeichertunderhältdenWert
1000–dieAdressederneuenInstanz
45
InZeitlupe
public void run() {
Rational a = new Rational(1, 2);
public Rational add(Rational r) {
36
5
Rational b = new Rational(1, 3);
2
1
3
1
Rational c = new Rational(1, 6);
return new Rational( this.num * r.den + r.num * this.den ,
Rational sum = a.add(b).add(c);
this.den * r.den );
println(a
+ " + " + b++""++""++bc++""+=""++csum);
System.out.println(a
+ " = " + sum);
}}
36
6
heap
stack
TestRa=onal
1000
num
den
1
1004
1004
2
1008
1008
num
den
1
1010
1010
3
1014
1014
num
den
1
101C
101C
6
1020
1020
num
den
5
1028
1028
6
102C
102C
num
den
1
1034
1034
1
1038
1038
100C
100C
1018
1018
1/2 + 1/3 + 1/6 = 1
All objects are created
in the heap.
This object is a temporary value
used only during
the100C
calculation.
FFE0
r
1018
1000
1024
sum
c
b
a
1030
FFEC
1018
FFF0
100C
1000
FFF4
This stack frame is created
for the add method.
FFE8
1024
1024
1030
1030
FFE4
this
This stack frame is created
for the run method.
FFF8
FFFC
skip simulation
ExplizitePointer
!  DieSkizzelinkszeigtdenZustanddesSpeichersamEndeder
Methode run ausTestRational.
!  DasBildrechtszeigtdenselbenZustandmiteinemPfeil
(“Pointer”)anstellederAdresse(PointerModell)
heap
stack
heap
stack
1000
num
den
1
1004
2
1008
num
den
1
num
den
1
num
den
1
num
den
5
num
den
1
2
100C
num
den
1
1010
3
1014
3
1018
num
den
1
101C
6
1020
6
1024
num
den
5
1028
6
102C
num
den
1
1034
1
1038
1030
sum
c
b
a
1030
FFEC
1018
FFF0
100C
FFF4
1000
FFF8
FFFC
6
1
sum
c
b
a
Adressenvs.Pointer
BeideSkizzen(mitAdressenoderPointern)zeigendenselbenZustand
aberbetonenunterschiedlicheAspekte.
–  AdressenverdeutlichendassVerweise(References)eineZahlenthalten.
–  DasPointerModellbetontdieBeziehungzwischenReferenz(variable)
undObjekt(instanz).
heap
stack
heap
stack
1000
num
den
1
1004
2
1008
num
den
1
num
den
1
num
den
1
num
den
5
num
den
1
2
100C
num
den
1
1010
3
1014
3
1018
num
den
1
101C
6
1020
6
1024
num
den
5
1028
6
102C
num
den
1
1034
1
1038
1030
sum
c
b
a
1030
FFEC
1018
FFF0
100C
FFF4
1000
FFF8
FFFC
6
1
sum
c
b
a
Nicht-erreichbareObjekte
Das Pointer Modell macht klar das es keinen Verweis auf die
Rational Instanz5/6gibt.DieserWertistjetzt“Garbage”.
DasJavaLaufzeitsystemführtvonZeitzuZeiteineSpeicherbereinigungdurch(“garbagecollec9on”)–automaIsch
heap
Instanz die temporär gebraucht wurde
aber jetzt unerreichbar ist.
num
den
1
num
den
1
num
den
1
num
den
5
num
den
1
stack
2
3
6
6
1
sum
c
b
a
Uebung:Stack-HeapDiagramm
GegebensindKlassen Point undLine wiefolgt
public class Point {
public Point(int x, int y) {
cx = x;
cy = y;
}
. . . other methods appear here . . .
}
public class Line {
public Line(Point p1,
Point p2) {
start = p1;
finish = p2;
}
. . . other methods appear here . . .
private int cx;
private int cy;
}
private Point start;
private Point finish;
Zeichnen Sie ein Stack-Heap Diagramm für den Zustand
desSpeichersbevordieMethoderun auyört.
public void run() {
Point p1 = new Point(0, 0);
Point p2 = new Point(200, 200);
Line line = new Line(p1, p2);
}
Lösung
AddressModel
PointerModel
heap
stack
heap
stack
1000
cx
cy
0
1004
0
1008
cx
cy
0
cx
cy
200
0
100C
cx
cy
200
1010
200
1014
1018
start
finish
1000
101C
100C
1020
line
p2
p1
1018
FFF0
100C
FFF4
1000
FFF8
FFFC
start
finish
200
line
p2
p1
BasistypenvsObjekte
!  EinBasistypParameterwirdnachdenRegelnderValue
Seman9csübergeben.
!  EinParameterfüreineReferenzvariablefolgtdenRegelnder
ReferenceSeman9cs.
!  NuraufdenerstenBlickscheintes,dassBasistypenund
Referenztypenunterschiedlichbehandeltwerden.
52
!  WennwireineBasistypVariablealsParameterübergeben,
dannkopierenwirdenWertderVariable
!  VeränderungeninderMethodehabendaherkeineWirkung
!  WennwireinReferenzvariablealsParameterübergeben,so
kopierenwirdieReferenz(mitderAdresse)
!  DaherkönnenwirdieInstanz,diewirüberdieAdresseerreichen,
verändern
!  EntwederüberAccessor/MutatorMethodenoderdurchdirekten
ZugriffaufeinAxribut
53
Verantwortlichkeiten
!  SehenwirunsnochmaldieMethodegcd(inRational)an:
/**
* Calculates the greatest common divisor
* using Euclid's
algorithm.
* @param x First integer
* @param y Second integer
* @return The greatest common divisor of x and y
*/
int gcd(int x, int y) {
int r = x % y;
while (r != 0) {
x = y;
y = r;
r = x % y;
}
return y;
}
54
int gcd(int x,
int r = x %
while (r !=
x = y;
y = r;
r = x %
}
return y;
int y) {
y;
0) {
y;
}
!  WasfürAnnahmenmachtdieseMethode?
!  LiefertsieimmerdasgewünschteErgebnis?
!  WasfürFällesolltenwiruntersuchen?
!  SchreibenSiedieFälleauf,dieSiefür"interesssant"halten
!  SimulierenSiedieAusführung
55
Verantwortlichkeiten
!  DieseImplementaIondesggTerwartet
!  x≥0
!  y>0
!  Weristdafür"verantwortlich"?
!  Klient?
!  (OK,hieristderKlientdieselbeKlasseRational)
!  DieMethode?
56
Verantwortlichkeiten
!  (Teil)Lösunghier
gcd(Math.abs(x), Math.abs(y));
!  Kommentarwärenichtverfehlt
!  gcd kanndavonausgehendassx≥0
!  "x≥0"isteineAussagediehierimmergilt
!  Nichtgelöstistdassy≠0seinmuss
!  Beispielsollnichtüberladenwerden
57
Herunterladen