Denna laboration bör du klara av efter att ha läst kapitel 1-3 i kursboken. Avsikten med laborationen är att du skall bli säker på grundläggande objektorienterade begrepp såsom klasser, objekt, instansmetoder, instansvariabler och konstruktorer.
Uppgiften är att konstruera en klass RatNum som representerar rationella tal. Ett rationellt tal uttrycks som bekant som kvoten mellan två heltal. Vi skriver rationella tal på formen 1/3, −1/5.
De testprogram och exempelfiler som hör till labben innehåller åäö och är kodade enligt UTF8. Om din plattforms förvalda encoding är något annat kan det uppstå problem när du kompilerar. Du kan lösa problemet genom att använda flaggan
-encoding "UTF8"
För att förenkla arbetet har laborationen delats in i tre steg och för varje steg finns ett testprogram som ni kan (och bör) använda för att bekräfta att er klass fungerar som den ska hittills.
När man beskriver rationella tal är det bäst att förkorta bort alla gemensamma faktorer i täljaren och nämnaren. För att kunna göra denna förkortning behövs en metod som beräknar den största gemensamma divisorn till två heltal m
och n
. Skriv en sådan metod! Kalla metoden (som ska vara en klassmetod d.v.s. statisk metod) sgd
och placera den i en klass med namnet RatNum
. Metoden ska acceptera att m
och n
är både positiva och negativa argument, men inte 0. Resultat ska vara största gemensamma divisor för absolutbeloppen av m
och n
. Utforma din metod så att den genererar en exception av typen IllegalArgumentException
om någon av parametrarna är lika med noll. Detta kan göras med satsen
throw new IllegalArgumentException();
Tips: Euklides algoritm för att beräkna den största gemensamma divisorn till två positiva heltal m
och n
kan beskrivas på följande sätt:
m
med n
och låt r
vara resten vid divisionen.r
= 0 så är beräkningen klar och resultatet finns i n
.m
till n
och n
till r
och gå tillbaka till steg 1.Denna algoritm fungerar om talen m
och n
båda är positiva. Se därför i metoden sgd
till att parametrarna alltid görs positiva innan algoritmen tillämpas.
Testa metoden sgd
genom att kopiera det färdiga huvudprogrammet RatNumTest1
till samma bibliotek som klassen RatNum
. Kompilera och kör programmet!
Det är nu dags att börja fylla i klassen RatNum
så att den kan användas för att representera rationella tal. För varje objekt av klassen RatNum
skall täljaren och nämnaren lagras som två heltal. Dessa skall alltid sakna gemensamma faktorer, d.v.s. ett rationellt tal skall alltid vara avkortat så långt det går. Nämnaren måste alltid vara större än noll. Negativa rationella tal representeras med en negativ täljare. Om täljaren är 0 ska nämnare vara 1.
I detta steg skall du förse klassen RatNum
med följande konstruktorer och (instans)metoder:
En konstruktor utan parametrar som initierar det aktuella talet till 0/1.
En konstruktor med en parameter a
, som initierar objektet att representera heltalet a
.
En konstruktor med två parametrar, a
och b
vilka betecknar täljaren och nämnaren. Objektet ska initieras till att representera a
och b
. Kom ihåg att täljaren och nämnaren i ett RatNum
ska sakna gemensamma faktorer. Om b är lika med noll skall en exception av typen NumberFormatException
genereras. Detta kan göras med satsen
throw new NumberFormatException("Denominator = 0");
När du implementerar denna konstruktorn har du nytta av metoden sgd
.
En konstruktor (en s.k. kopieringskonstruktor) som tar ett annat rationellt tal som argument och kopierar detta.
En metod getNumerator
som returnerar talets täljare.
En metod getDenominator
som returnerar talets nämnare.
Testa klassen RatNum
genom att kopiera det färdiga huvudprogrammet RatNumTest2
till samma bibliotek som klassen RatNum. Kompilera och kör programmet! Läs sedan programkoden för huvudprogrammet RatNumTest2 och förvissa dig om att du förstår vad detta program gör.
Klassen skall nu utökas med några metoder, vilka förenklar inläsning och utskrift av rationella tal och gör det möjligt att utföra matematiska operationer på rationella tal. Följande metoder skall läggas till:
En metod toString
som returnerar det aktuella talet som en text med formen "a/b"
. (Som extrauppgift kan du senare, när resten av klassen är klar, utöka metoden toString så att den presenterar resultatet med formen "h d/n"
, där h
är heltalsdelen av divisionen a/b
och d
resten. Om det ärfråga om ett negativt tal skall man i detta fall presentera resultatet med formen -h d/n.)
En metod toDouble
som returnerar ett närmevärde för det aktuella talet.
En klassmetod (statisk metod) parse
som har en parameter s
av typen String
. Parametern skall undersökas och om den innehåller en text som på ett korrekt sätt beskriver ett rationellt tal skall ett nytt rationellt tal (ett nytt RatNum
-objekt) med det angivna värdet skapas och returneras. (Jämför med metoden parseInt
i standardklassen Integer
.) Texten i parametern s
får ha någon av fyra följande former, där a
och b
betecknar icke-negativa tal: "a/b"
, "–a/b"
, "a/-b"
, "a"
eller "-a"
. Det får inte finnas några blanka tecken. Den sista formen visar att det är tillåtet att bara ange täljaren. Om texten i s
ser ut på ett otillåtet sätt skall parse
generera en exception av typen NumberFormatException
.
En konstruktor med en parameter av typen String. Om parametern innehåller en text som på ett korrekt sätt beskriver ett rationellt tal (enligt punkten ovan) skall det nya talet initieras, annars skall en exception av typen NumberFormatException
genereras.
En parameterlös metod clone
som skapar en kopia av det aktuella talet. Som returvärde ger metoden en referens till kopian. För att denna metod skall följa mönstret i Java
ska returtypen inte vara RatNum
, utan Object
(som är en superklass till alla klasser).
En metod equals
som har ett annat rationellt tal som parameter vilket jämförs med det talet självt. Om de två talen är lika returneras true
annars false
.
En metod lessThan
som har ett annat rationellt tal som parameter och avgör om talet självt är mindre än detta tal.
En metod add
som har ett annat rationellt tal r
som parameter. Som resultat ges ett nytt rationell tal som är summan av talet självt och r
.
En metod sub
som har ett annat rationellt tal r
som parameter. Som resultat ges ett nytt rationell tal som är differensen mellan talet självt och r
.
En metod mul
som har ett annat rationellt tal r
som parameter. Som resultat ges ett nytt rationell tal som är produkten av talet självt och r
.
En metod div
som har ett annat rationellt tal r
som parameter. Som resultat ges ett nytt rationell tal som är kvotet av talet självt och r
.
När klassen RatNum
är klar skall den testas tillsammans med det färdiga huvudprogrammet RatNumTest3
. Studera detta program i detalj och sätt dig in i hur det fungerar! När man kör det färdiga huvudprogrammet tillsammans med sin klass RatNum
kan det se ut på följande sätt:
Skriv uttryck på formen a/b ? c/d, där ? är något av tecknen + - * / = <
> 1/3 + 1/5
1/3 + 1/5 --> 8/15
> 2/3 * 2/5
2/3 * 2/5 --> 4/15
> 1/3 - 2/5
1/3 - 2/5 --> -1/15
> 2/3 / 2/5
2/3 / 2/5 --> 1 2/3
> -2/3 - 2/5
-2/3 - 2/5 --> -1 1/15
> 2/11 < 1/5
2/11 < 1/5 --> true
> 3/15 = 1/5
3/15 = 1/5 --> true
> 5 / 2/3
5 / 2/3 --> 7 1/2
> 5/9 * 2
5/9 * 2 --> 1 1/9
>
För att underlätta testningen av klassen RatNum
finns det en färdig fil indata.txt
som du kan använda om du vill. Du kör den genom att i en kommandotolk ge kommandot
java RatNumTest3 < indata.txt
Utskriften som programmet då ger kan jämföras med "facit" som finns i filen utdata.txt
. Innan ni lämnar in labbar ska ni ha kontrollerat att resultatet för indata.txt
motsvara utdata.txt
.
Dokumentationen skall för labben ska innehålla den utskrift programmet RatNumTest3
producerar när det körs med filen indata.txt
som indata. I dokumentationen ska ni också med egna ord ge en beskrivning av vad det färdiga huvudprogrammet RatNumTest3
gör och hur det fungerar.
Skicka in följande (lösa fil, ej inuti .zip eller dylikt):
RatNum.java
-- er implementation av klassendok.txt
-- er dokumentationTänk på att följa de allmänna riktlinjerna för programmeringsstil som anges på sidan Laborationer.