Skip to content

Commit

Permalink
deploy: 67dcf7e
Browse files Browse the repository at this point in the history
  • Loading branch information
bart314 committed Sep 21, 2023
1 parent 533d65c commit 8ca6f49
Show file tree
Hide file tree
Showing 60 changed files with 4,645 additions and 2 deletions.
Binary file added _images/opionalint-documentatie.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added _images/point-documentatie.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions _sources/course/ex_3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Opgaven week 3

- Opgave 1: [Grote getallen](../exercises/grote_getallen.md)
- Opgave 2: [De klasse `OptionalInt`](../problems/opgave-OptionalInt.md)
- Opgave 3: [De klasse `LocalDate`](../problems/opgave-LocalDate.md)
39 changes: 39 additions & 0 deletions _sources/exercises/grote_getallen.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Grote getallen

## Machtsverheffing

Schrijf een recursieve methode `pow` die een `double` `x` en een `int` `n` accepteert en $x^n$ teruggeeft.

```{hint}
Een recursieve definitie van deze bewerking is $x^n = x \cdot x^{n-1}$.
Onthoud ook dat alles wat tot de macht nul verheven is, 1 is.
```

Optionele uitdaging: je kunt deze methode efficiënter maken, als $n$ even is, door $x^n = \left( x^{n/2} \right)^2$ te gebruiken.

## Faculteit

De faculteit van een getal is het product van de getallen 1 tot en met $n$. De recursieve uitwerking is als volgt

```java
public static int factorial(int n) {
if (n == 1) {
return 1;

return n * factorial(n - 1);
}
```

1. Maak een programma `Big.java` en herschrijf daar de recursieve versie van `factorial` naar een *iteratieve* versie met behulp van een `for`-lus.

2. Houd een tabel bij van de gehele getallen van 0 tot 30 samen met hun faculteit. Op een bepaald punt rond 15 zul je waarschijnlijk zien dat de antwoorden niet meer juist zijn. Waarom niet?

3. Converteer `factorial` zodat het de berekening uitvoert met het type `BigInteger` en een `BigInteger` als resultaat teruggeeft. Je kan parameter parameter type laten staan, het zal nog steeds een geheel getal (`int`) zijn.

4. Probeer de tabel opnieuw bij te houden met jouw aangepaste `factorial` methode. Is het correct tot 30? Hoe hoog kun je het laten gaan?

5. Optioneel: bij de vorige opgave zal je tegen hetzelfde probleem aanlopen zodra de getallen groter worden. Pas jouw recursieve methode `pow` aan zodat het ook het type `BigInteger` gebruikt.

```{note}
De opgave Machtsverheffing kan je in het boek vinden in [hoofdstuk 9](https://books.trinket.io/thinkjava2/chapter6.html), de opgave Faculteit in [hoofdstuk 8](https://books.trinket.io/thinkjava2/chapter6.html).
```
163 changes: 163 additions & 0 deletions _sources/exercises/objecten_maken_met_point.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
# Practicum: Objecten maken van klasse Point

Dit practicum is een kennismaking met het maken van en werken met objecten in Java.

## Klasse `Point`

De klasse `Point` representeert een punt in een twee-dimensionaal vlak. Een object maken van een klasse wordt in de regel gedaan met het *keyword* *new*:

`<niet-primitief-type> *variabeleNaam* = new <klasse>([argumenten]);`

Bijvoorbeeld het maken van een object van klasse `Point`:
De onderstaande code maakt bijvoorbeeld een instantie van klasse `Point`. De *referentie* naar dit object wordt opgeslagen in de variabele `point1` Een instantie (Engels: *instance*) is een object.

```{code-block} java
Point point1 = new Point();
System.out.println(point1.x + "," + point1.y);
```

Deze klasse is standaard in Java aanwezig, maar om hem beschikbaar te maken dient deze geïmporteerd te worden met de onderstaande regel:

```{code-block} java
import java.awt.Point;
```

De import staat in de code *boven* de klasse-definitie maar *onder* de regel die begint met `package` (deze regel is niet altijd aanwezig, in dat geval staan de imports helemaal aan het begin). Een geavanceerde editor zoals IntelliJ zet de imports vaak automatisch in de code.

Maak een klasse `PracticumPoint` met daarin een main-methode. Neem bovenstaande code over in main. Zorg ook voor de import van `Point`, door de import-regel bovenin `PracticumPoint.java` te plaatsen. Wat zijn de coördinaten van het punt?

De coördinaten van `point1` opvragen of veranderen kunnen we doen door de properties `x` en `y` rechtstreeks te benaderen:

```{code-block} java
point1.x = 5;
point1.y = 3;
System.out.println(point1.x + "," + point1.y); // 5,3
```

Voeg bovenstaande regels code toe en test het programma.

Voeg code toe om de `x`-coördinaat te verhogen met 10. Print vervolgens de coördinaten op het scherm.

```{code-block} java
point1.x = point1.x + 10;
System.out.println(point1.x + "," + point1.y); // 5,3
```

De variabelen `x` en `y` zijn *properties* van *instanties* van `Point`. Properties van een object worden ook wel *instantie-variabelen* genoemd. Het rechtstreeks benaderen van instantie-variabelen van een object, buiten het object, is ongebruikelijk. Hoewel het technisch gezien kan, is binnen Java de gewoonte (conventies) om instantie-variabelen altijd te lezen of veranderen door middel van aanroep van methodes, zogenaamde `getters` en `setters`.

In de meeste klassen is het rechtstreeks benaderen van instantie-variabelen zelfs onmogelijk gemaakt. De voornaamste reden dat dit bij `Point` niet het geval is, is dat deze klasse al onderdeel is van de allereerste versie van Java, toen men wat losser omging met properties.

## Methodes

*Methodes* zijn vergelijkbaar met *functies* maar ze zijn onderdeel van een bepaalde klasse. Ze zijn beschikbaar via een *klasse* of *object*. Met de onderstaande code kun je bijvoorbeeld de *property* `x` van `point1` opvragen (dat is zo'n `getter` waar we het eerder over hadden):

`System.out.println( point1.getX() );`

Met de methodes `getX()` en `getY()` worden de coördinaten opgevraagd. Met de methode `setLocation(int x, int y)` worden de coördinaten veranderd.

Herschrijf de code in je `main` methode zodat de properties `x` en `y` niet meer worden gebruikt. In plaats daarvan maak je gebruik van de bovenstaande methodes.

## Constructors

Bij het maken van een instantie met keyword `new` kunnen argumenten worden meegegeven. Soms is dit verplicht, maar in het geval van `Point` niet. Welke argumenten kunnen worden meegegeven wordt gedefinieerd in de constructor. Soms zijn er meerdere constructors gedefinieerd, waarbij meerdere soorten argumenten mogelijk zijn (*constructor overloading*, vergelijkbaar met *method overloading*).

De klasse Point heeft drie constructors: `Point()`, `Point​(int x, int y)` en `Point​(Point p)`. Voeg code toe om een tweede instantie van `Point` te maken met de naam `point2`. Geef aan de constructor de coördinaten `(1, 2)` mee, door de argumenten 1,2 tussen haakjes te zetten achter `new Point`. Print de coördinaten op de console om te testen.

## Documentatie

Alle met Java meegeleverde klassen zijn uitvoerig gedocumenteerd. Zo is de documentatie van `Point` te vinden via [deze link](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/java/awt/Point.html).

Onder het kopje "Constructors" vind je de *constructors*. Onder "Method Summary" vind je een overzicht van alle methodes (je verwacht het niet).

![De documentatie op oracle.com](../images/point-documentatie.png)

Voeg code toe om `point2` 3 plekken naar rechts en 1 naar onder te verplaatsen. Dit kan gerealiseerd worden met een combinatie van `setLocation`, `getX` en `getY`, maar er is ook een methode die dit in één keer kan doen. Zoek in de documentatie naar deze methode en maak daar gebruik van. Print de nieuwe coördinaten.

## Methode `toString()`

Elk object heeft de methode `toString()`. Niet elke klasse heeft een specifieke implementatie, maar als dit het geval is dan geeft `toString()` een string terug met daarin de belangrijkste informatie over een object. Als een object op het scherm wordt afgedrukt met `System.out.println()` dan zorgt de JVM er zelf voor dat `toString()` wordt aangeroepen. Dit is ook het geval als een object aan een string wordt "geplakt" met de + operator (*string concatenation).

Probeer de regels `System.out.println(point2.toString())` en `System.out.println(point2)` uit; kun je het verschil in uitkomsten verklaren?

## Methodes met objecten

Je kunt ook objecten meegegeven worden aan methoden; of, om het preciezer te formuleren, je kunt *verwijzingen* naar objecten meegegeven aan methoden. Dit zijn niet-primitieve datatypes.

Schrijf de volgende methode:

```{code-block} java
public static boolean isClose(Point p1, Point p2)
```

De methode retourneert `true` als de afstand tussen beide punten kleiner is dan 2,5, en `false` als dit niet het geval is. De afstand tussen twee punten wordt berekend met de stelling van Pythagoras:

$$
distance = \sqrt{(x_2-x_1)^2 + (y_2-y_1)^2}
$$

Je kunt het onderstaande code-blok gebruiken om de methode te testen:

```{code-block} java
Point point3 = new Point(2,3);
System.out.println(isClose(point3, new Point(3,3))); // true
System.out.println(isClose(point3, new Point(0,2))); // true
System.out.println(isClose(point3, new Point(0,5))); // false
```

## Foutje...

Gegeven de volgende methode:

```{code-block} java
public static Point between(Point p1, Point p2) {
double betweenX = (p1.getX() + p2.getX()) / 2;
double betweenY = (p1.getY() + p2.getY()) / 2;
p1.setLocation( betweenX, betweenY );
return p1;
}
```

De methode `between` retourneert het punt dat zich precies tussen de punten `p1` en `p2` bevindt. Coördinaten zijn altijd gehele getallen (*integers*).

Deze test suggereert dat de methode goed werkt:

```{code-block} java
Point point4 = new Point(5, 3);
Point point5 = new Point(15, 7);
System.out.println(between(point4, point5)); // [x=10,y=5]
```

De methode bevat echter een ernstige fout. Welke fout? Hint: Controleer na uitvoeren van de methode niet alleen naar de return-waarde, maar ook naar `point4` en `point5`...

Verbeter de fout.

## Nog een foutje..

Gegeven de volgende code:

```{code-block} java
Point player = new Point(3, 10);
Point monster = new Point(25, 10);
// De loop moet stoppen zodra de speler bij het monster is (als de coördinaten gelijk zijn)
while(player!=monster) {
player.translate(1,0);
System.out.println("Move.."+player);
}
System.out.println("Game over");
```

De bedoeling is dat de speler steeds een stap zet, totdat de speler bij het monster is. Dit is het geval als de coördinaten van `player` en `monster` gelijk zijn.

Test de code. De code bevat een ernstige fout. Welke?

Er zijn twee correcte manieren om de coördinaten van `player` en `monster` te vergelijken. Allereerst het vergelijken van zowel de `x`- als de `y`-coördinaten. Verbeter op deze wijze de fout.

Een andere manier is het vergelijken van de inhoud van de objecten. Dit lijkt te gebeuren in de gegeven code, maar dit is niet het geval. Inhoud van objecten wordt vergelijken met de `equals` methode. Verbeter de fout door gebruik te maken van de `equals` methode.

De `equals` methode is de gangbare manier om de inhoud van objecten te vergelijken. Wat exact wordt vergeleken, hangt af van de klasse. Net als `toString` is de methode `equals` altijd aanwezig, maar het verschilt per klasse of deze volledig is geïmplementeerd.






63 changes: 63 additions & 0 deletions _sources/problems/opgave-LocalDate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Opgave Klasse `LocalDate`

De klasse `LocalDate` representeert een datum in de plaatselijke tijdzone.

De *constructor* van `LocalDate` is niet *public*, waardoor het niet mogelijk is om met het keyword `new` instanties te maken van `LocalDate`.

De documentatie van `LocalDate` is [hier te vinden](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/LocalDate.html)

Onder "Method Summary" - "Static Methods" zijn methodes te vinden waarmee instanties van `LocalDate` worden gemaakt. Daarvan zijn `now` en `of` het belangrijkst.

## Voorbeeld

Zie het voorbeeld hieronder:

```{code-block} java
LocalDate vandaag = LocalDate.now();
LocalDate lustrum = LocalDate.of(2023, 10, 18); // Hanze lustrum 18 oktober 2023
System.out.println("Vandaag: " + vandaag);
System.out.println("Hanze lustrum '23: " + lustrum);
if (vandaag.isAfter(lustrum)) {
System.out.println("Het Hanze lustrum feest is al geweest.");
} else {
long d = ChronoUnit.DAYS.between(vandaag, lustrum);
System.out.println("Over " + d + " dagen is het feest");
}
```

De uitvoer van `LocalDate` op het scherm (om precies te zijn: de `toString` methode van `LocalDate`) geeft geen 'mooie' datum, maar een standaard weergave in het *iso8601-formaat* YYYY-MM-DD.

## Werken met de klasse `LocalDate`

Maak de onderstaande opgaven. Zoek in de documentatie naar geschikte methodes. Als er wordt gevraagd om een datum op het scherm af te drukken, dan kun je volstaan met een standaard weergave. Als gevraagd wordt naar een weekdag dan is het voldoende om de weekdagen in het Engels af te drukken, zoals deze wordt teruggegeven door bijvoorbeeld de methode `getDayOfWeek`.

## Kleine opgaven

We beginnen met wat eenvoudige opgaven om op te warmen. Druk de antwoorden van de onderstaande vragen af:

- Op welke weekdag valt 10 januari 1965?
- Op welke weekdag viel nieuwjaarsdag (1 januari) in het huidige kalenderjaar?
- Wat is de datum vijf weken na vandaag?
- Hoeveel dagen is het geleden dat Nederland het Europees kampioenschap voetbal won (op 25 juni 1988)?

## Huidige collegejaar

Een collegejaar loopt van 1 september tot 1 september van het jaar daarop. Om welk collegejaar het gaat wordt vaak aangegeven met jaartallen. Zo wordt het collegejaar dat begint op 1 september 2023 aangegeven met '23-'24.

Zet het huidige collegejaar op het scherm. Bedenk een methode om het programma te testen, zodat je zeker weet dat het programma over bijvoorbeeld 9 maanden ook nog de het juiste collegejaar aangeeft.

## Kerst

Kerst valt elk jaar op 25 en 26 december. Zet op het scherm hoeveel dagen het nog duurt, voordat het kerst is (eerste kerstdag).
Als het nu eerste of tweede kerstdag is, zet dan op het scherm dat het nu kerst is.

## Sinterklaas

Sinterklaas is elk jaar op 5 december. Zet op het scherm de eerstvolgende 10 datums waarop Sinterklaas plaatsvindt. Zet bij elke datum ook op welke weekdag het plaatsvindt.
Als het vandaag Sinterklaas is, dan telt deze mee met de 10.

## Prinsjesdag

Prinsjesdag is elk jaar op de derde dinsdag van september. Zet op het scherm de eerstvolgende 5 datums waarop prinsjesdag plaatsvindt.
Als het vandaag prinsjesdag is, dan telt deze mee met de 5 datums op het scherm.

77 changes: 77 additions & 0 deletions _sources/problems/opgave-OptionalInt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Opgave klasse `OptionalInt`

Deze opgave gaat over de klasse `OptionalInt`. Deze klasse is handig als het mogelijk moet zijn om een integer-waarde terug te geven waarbij het ook mogelijk is dat er geen waarde aanwezig is (`empty`).

Naast `OptionalInt` bevat Java ook `OptionalLong`, `OptionalDouble` en de generieke `Optional<T>`.

## Casus: *Break-even* punt berekenen

Er is sprake van een *break-even* punt wanneer er geen winst en geen verlies wordt gemaakt.

Stel dat de kosten voor het maken van een product 80 euro per stuk bedragen. Behalve deze variabele kosten moet er 1000 gereserveerd worden voor de vaste lasten. Het product wordt verkocht voor 100 euro. Per stuk wordt dan 20 euro winst gemaakt ten opzichte van de variabele kosten (€100 - €80 = €20). Om geen verlies meer te maken moeten minimaal 50 stuks worden verkocht (immers €1000 / 20 stuks = 50).

Met de volgende methode wordt het break-even punt berekend van verkoop van een product aan de hand van vaste kosten, de kosten per stuk en opbrengst per stuk:

```{code-block} java
public static int berekenBreakeven(double vasteKosten, double kostenPerEenheid, double opbrengstPerEenheid) {
double winstPerEenheid = opbrengstPerEenheid - kostenPerEenheid;
return (int)Math.ceil(vasteKosten / winstPerEenheid);
}
```

De volgende hulp-methode wordt gebruikt om het break-even punt op een nette manier weer te geven:

```{code-block} java
public static void printBreakeven(double vasteKosten, double kostenPerEenheid, double opbrengstPerEenheid) {
int n=berekenBreakeven(vasteKosten, kostenPerEenheid, opbrengstPerEenheid);
System.out.println("Break-even punt: "+n+" eenheden.");
}
```

## De klasse `OpgaveOptionalInt`

Maak een klasse `OpgaveOptionalInt` met daarin de methodes `berekenBreakeven` en `printBreakeven`. Maak een `main` methode waarin je de onderstaande testcode zet. Klopt het resultaat?


```{code-block} java
printBreakeven( 1000, 80, 100 ); // 50
printBreakeven( 12000, 0.75, 1.30 ); // 21819
```


## Geen break-even punt

Wat is het resultaat van de volgende test-aanroep?

```{code-block} java
printBreakeven( 2500, 12, 10.5 );
```

Is dit resultaat reëel/valide?

Pas de methode `printBreakeven` zodanig aan dat in het geval van geen break-even punt op het scherm "Geen break-even punt" wordt afgedrukt.

## Ongeldige waardes

Als een uitkomst niet reëel of valide is, dan heeft dit vaak te maken met ongeldige invoerwaardes. Het afhandelen van ongeldige argumenten is geen onderwerp van deze opgave. De argumenten zijn in dit geval juist wel geldig. Er zijn reële situaties denkbaar waarbij de kostprijs hoger is dan de opbrengst.

Het break-even punt is negatief omdat de variabele koste hoger zijn dan de opbrengst per stuk. De uitkomst is niet reëel, want het is normaal gesproken niet mogelijk om een negatief aantal producten te verkopen. Wat is in dat geval wenselijk om te retourneren?

Als een integer geretourneerd moet worden, dan zijn alleen gehele getallen mogelijk als resultaat. De getallen 0 en hoger zijn break-even punten. Eventueel zou een negatief getal gebruikt kunnen worden in het geval er geen break-even punt is. Probleem is dit een enigszins merkwaardig resultaat is, omdat het de suggestie wekt dat het aantal producten negatief kan zijn. Stel dat een programmeur hier geen rekening mee houdt, en bijvoorbeeld gemiddelden gaat berekenen, dan kunnen er ongemerkt vreemde uitkomsten onstaan.

Een ideale oplossing zou de mogelijkheid zijn om aan te geven dat er *geen uitkomst* is. Hoewel dit in sommige gevallen met `None` of `null` mogelijk is en wordt gedaan (met een omweg ook in Java) hebben deze waardes strikt genomen niet dezelfde betekenis als geen waarde. Het niet-primitieve datatype `OptionalInt` biedt de mogelijkheid om naast een bepaalde integer-waarde aan te geven dat er geen waarde is.

## OptionalInt gebruiken

De documentatie van OptionalInt is te vinden op [de documentatie van Oracle](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/OptionalInt.html). Pas de methode `berekenBreakeven` zo aan dat in plaats van een `int` een `OptionalInt` wordt geretourneerd.

Als er geen break-even punt is, dan is deze `OptionalInt` empty (maak geen gebruik van `null`). Onder 'Static Methods' in de documentatie vind je de methodes om instanties te maken van `OptionalInt`.

Pas ook `printBreakeven` aan, zodat deze gebruik maakt van de `OptionalInt`.

![De statische methoden van `OptionalInt`](../images/opionalint-documentatie.png)





32 changes: 32 additions & 0 deletions about/literatuur.html
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,38 @@ <h1 class="site-logo" id="site-title">Objectgeoriënteerd Programmeren</h1>
</li>
</ul>
</li>
<li class="toctree-l1">
<a class="reference internal" href="../exercises/objecten_maken_met_point.html">
Practicum
</a>
</li>
<li class="toctree-l1 has-children">
<a class="reference internal" href="../course/ex_3.html">
Opgaven week 3
</a>
<input class="toctree-checkbox" id="toctree-checkbox-6" name="toctree-checkbox-6" type="checkbox"/>
<label for="toctree-checkbox-6">
<i class="fas fa-chevron-down">
</i>
</label>
<ul>
<li class="toctree-l2">
<a class="reference internal" href="../exercises/grote_getallen.html">
Grote getallen
</a>
</li>
<li class="toctree-l2">
<a class="reference internal" href="../problems/opgave-OptionalInt.html">
De klasse `OptionalInt`
</a>
</li>
<li class="toctree-l2">
<a class="reference internal" href="../problems/opgave-LocalDate.html">
De klasse `LocalDate`
</a>
</li>
</ul>
</li>
</ul>

</div>
Expand Down
Loading

0 comments on commit 8ca6f49

Please sign in to comment.