Gå til innhold

[Løst] Regne med brøk


Anbefalte innlegg

Heisann! Jeg holder på med en oppgave fra boken "Pogrammering i java", og står fast på en oppgave som jeg ikke helt forstår hvordan jeg skal løse.

 

 

Oppgave
Lag en klasse for å regne med brøk.
Klassen skal ha to konstruktører:

  • Den ene konstruktøren tar teller og nevner som argument. Hvis neveneren er 0, skal et unntaksobjekt av typen IllegalArgumentException kastes.
  • Den andre konstruktøren tar kun telleren som argument. Da skal nevneren settes lik 1.

Klassen skal ha get-metoder, men ikke set-metoder.
Klassen skal ha metoder for å summere, subtrahere, multiplisere og dividere en brøk (this) med en annen brøk (parameter til metoden). Metodene har ikke returverdi, men etter at operasjonen er utført, ligger resultatet i this.
Du kan se bort fra at resultatet av opersajonen bør forkortes.
Lag en testklient som del av klassen.
Ekstraoppgave: Sørg for å forkorte brøkene.

 

 

De to setningene som forvirret meg mest var "Klassen skal ha metoder for å summere, subtrahere, multiplisere og dividere en brøk (this) med en annen brøk (parameter til metoden). Metodene har ikke returverdi, men etter at operasjonen er utført, ligger resultatet i this." Jeg skjønte ikke helt dette med "this".

Kapittelet heter "Klasser som byggeklosser", så jeg er ikke på så veldig avansert nivå enda kode-messig.

 

Er takknemmelig for all hjelp jeg kan få! :)

 

Dette er hva jeg har gjort, vet ikke hvordan jeg skal gjøre dette helt:


class Brok {

	    private int nevner; 
		private int teller;

		public Brok(int teller, int nevner) {
			this.teller = teller; 
			this.nevner = nevner; 
		}

		public Brok(int teller) {
			this.teller = teller; 
			this.nevner = 1; 
		}


		public void adder(..) {
            //??
		}

		public void subtraher(..) {
			//??
		}

		public void multipliser(..) {
			//??
		}

		public void divider(..) {
			//??
		}

	}


Endret av BloodySquito
Lenke til kommentar
Videoannonse
Annonse

"this" er navnet på et objekt. For eksempel om du instansierer en klasse som har en variabel x så kan du referer til den som this->x (eller er det this.x i Java?)

Du vil da ha behov for en resultatvariabel som inneholder svaret i klassen.

 

Tipper at det å returnere et brøkobjekt blir en oppgave i nær fremtid. :)

Lenke til kommentar

"this" er navnet på et objekt. For eksempel om du instansierer en klasse som har en variabel x så kan du referer til den som this->x (eller er det this.x i Java?)

 

Blir this.x i java ja

 

F.eks dette vil returnere klassobjektet.

public Broek getBroek(){
   return this;
}

Dette vil returnere variabelen teller innenfor klasseobjektet

public int getTeller(){
  return this.teller;
}
Lenke til kommentar

 

 

Blir this.x i java ja

 

F.eks dette vil returnere klassobjektet.

public Broek getBroek(){
   return this;
}

Dette vil returnere variabelen teller innenfor klasseobjektet

public int getTeller(){
  return this.teller;
}

Jeg vet sånn generelt hvordan this viker, tror bare ikke helt jeg skjønte den oppgaven helt. Jeg redigerte inn koden jeg har gjort til nå i innlegget mitt, ellers er jeg helt stuck :hm:

Endret av BloodySquito
Lenke til kommentar

Din første konstruktør er mangefull, les litt på try-catch setninger så skjønner du hva som blir sagt i oppgaven.

 

Du mangler get-metoder som sagt i oppgaveteksten.

 

Skriv inn i alle regnemetodene at de skal ta inn en instans av klassen Broek.

 

La meg hjelpe deg på vei i multiplikasjonen så se om du får til resten.

Hva er det som skjer når du multipliserer to brøker? Du ganger tellerne med hverandre, og nevnerne med hverandre. Da er det ikke verre enn at du du gjør det samme i koden og lagrer resultatet i this.

 

 

 

Eksempelkode på enkel tallmultiplikasjon:

public void multiplyNumber(int newNumber){
   this.number = this.number * newNumber;
}

Testkjøring:

public static void main(String[] args){
   HelloWorld hw = new HelloWorld(7);
   System.out.println(hw); // Skal gi utskrift på 7
   hw.multiplyNumber(2);
   System.out.println(hw); // Skal gi utskrift på 14
}

 

 

Lenke til kommentar

Din første konstruktør er mangefull, les litt på try-catch setninger så skjønner du hva som blir sagt i oppgaven.

 

Du mangler get-metoder som sagt i oppgaveteksten.

 

Skriv inn i alle regnemetodene at de skal ta inn en instans av klassen Broek.

 

La meg hjelpe deg på vei i multiplikasjonen så se om du får til resten.

Hva er det som skjer når du multipliserer to brøker? Du ganger tellerne med hverandre, og nevnerne med hverandre. Da er det ikke verre enn at du du gjør det samme i koden og lagrer resultatet i this.

 

 

 

Eksempelkode på enkel tallmultiplikasjon:

public void multiplyNumber(int newNumber){
   this.number = this.number * newNumber;
}

Testkjøring:

public static void main(String[] args){
   HelloWorld hw = new HelloWorld(7);
   System.out.println(hw); // Skal gi utskrift på 7
   hw.multiplyNumber(2);
   System.out.println(hw); // Skal gi utskrift på 14
}

 

 

 

 

Med mangelfull, mener du at IllegalArgumentException skal kastes? Ser jeg glemte å ta den med nå ja..

 

Men bør multiplikasjons-metoden inneholde 2 argumenter, en for teller og en for nevner?

 

Skal se om jeg får fullført oppgaven i morgen, takk for hjelpen! :)

Lenke til kommentar

Med mangelfull, mener du at IllegalArgumentException skal kastes? Ser jeg glemte å ta den med nå ja..

Ja

Men bør multiplikasjons-metoden inneholde 2 argumenter, en for teller og en for nevner?

Nei. Se hva jeg skrev lengre opp, og hva som står i oppgaven. Metodene for regning skal ta inn en BRØK.(HintHint)

Lenke til kommentar

Her er et (totalt udokumentert) forslag til hvordan en slik klasse kan se ut. Det er gjort noen valg som bryter med oppgaveteksten, det viktigste er at klassen er immutable, slik at et objekt ikke kan endres etter at det er kreert. Dette er kjekt mtp. på bruk i flertrådete systemer. Klassen kan minne litt om klassene Integer, Long osv. Du kan sikkert få noen idéer ved å se på koden.

public final class Fraction implements Comparable<Fraction> {

  private final int numerator;
  private final int denominator;

  private int gcd(int n, int d) {
    if (d == 0) {
      return n;
    } else {
      return gcd(d, n % d);
    }
  }

  public Fraction(int numerator) {
    this.numerator = numerator;
    this.denominator = 1;
  }

  public Fraction(int numerator, int denominator) {
    if (denominator == 0) {
      throw new IllegalArgumentException("Denominator cannot be zero");
    }
    if (denominator < 0) {
      denominator *= -1;
      numerator *= -1;
    }
    if (numerator == 0) {
      denominator = 1;
    } else {
      int gcd = gcd(numerator, denominator);
      while (gcd > 1) {
        numerator /= gcd;
        denominator /= gcd;
        gcd = gcd(numerator, denominator);
      }
    }
    this.numerator = numerator;
    this.denominator = denominator;
  }

  public Fraction add(int number) {
    return new Fraction(numerator + number * denominator, denominator);
  }

  public Fraction add(Fraction fraction) {
    return new Fraction(
            numerator * fraction.denominator
            + fraction.numerator * denominator,
            denominator * fraction.denominator);
  }

  public Fraction subtract(int number) {
    return new Fraction(numerator - number * denominator, denominator);
  }

  public Fraction subtract(Fraction fraction) {
    return new Fraction(
            numerator * fraction.denominator
            - fraction.numerator * denominator,
            denominator * fraction.denominator);
  }

  public Fraction multiply(int number) {
    return new Fraction(numerator * number, denominator);
  }

  public Fraction multiply(Fraction fraction) {
    return new Fraction(
            numerator * fraction.numerator,
            denominator * fraction.denominator);
  }

  public Fraction divide(int number) {
    return new Fraction(numerator, denominator * number);
  }

  public Fraction divide(Fraction fraction) {
    return new Fraction(
            numerator * fraction.denominator,
            denominator * fraction.numerator);
  }

  public float floatValue() {
    return numerator / (float)denominator;
  }

  public double doubleValue() {
    return numerator / (double)denominator;
  }

  @Override
  public int hashCode() {
    return numerator + denominator * 37;
  }

  @Override
  public boolean equals(Object obj) {
    if (!(obj instanceof Fraction)) return false;
    Fraction other = (Fraction)obj;
    return ((subtract(other)).numerator == 0);
  }

  @Override
  public String toString() {
    return numerator + "/" + denominator;
  }

  @Override
  public int compareTo(Fraction o) {
    return (this.subtract(o)).numerator;
  }

}
Lenke til kommentar

 

Her er et (totalt udokumentert) forslag til hvordan en slik klasse kan se ut. Det er gjort noen valg som bryter med oppgaveteksten, det viktigste er at klassen er immutable, slik at et objekt ikke kan endres etter at det er kreert. Dette er kjekt mtp. på bruk i flertrådete systemer. Klassen kan minne litt om klassene Integer, Long osv. Du kan sikkert få noen idéer ved å se på koden.

  private final int numerator;
  private final int denominator;

  private int gcd(int n, int d) {
    if (d == 0) {
      return n;
    } else {
      return gcd(d, n % d);
    }
  }

  public Fraction(int numerator) {
    this.numerator = numerator;
    this.denominator = 1;
  }

  public Fraction(int numerator, int denominator) {
    if (denominator == 0) {
      throw new IllegalArgumentException("Denominator cannot be zero");
    }
    if (denominator < 0) {
      denominator *= -1;
      numerator *= -1;
    }
    if (numerator == 0) {
      denominator = 1;
    } else {
      int gcd = gcd(numerator, denominator);
      while (gcd > 1) {
        numerator /= gcd;
        denominator /= gcd;
        gcd = gcd(numerator, denominator);
      }
    }
    this.numerator = numerator;
    this.denominator = denominator;
  }

  public Fraction add(int number) {
    return new Fraction(numerator + number * denominator, denominator);
  }

  public Fraction add(Fraction fraction) {
    return new Fraction(
            numerator * fraction.denominator
            + fraction.numerator * denominator,
            denominator * fraction.denominator);
  }


 

Jeg forstår det meste av koden, men nivået mitt er nok ikke like avansert.

 

Men om man går tilbake til min kode (litt mindre avansert) så prøvde jeg ut dette: (Uten å forkorte brøken):

 

 

public class Brok {

    private int teller;

    private int nevner;

    public Brok(int t, int n) {

	    if (n == 0) {

		    throw new IllegalArgumentException("Nevner kan ikke være 0");

	    }

	    this.teller = t;

	    this.nevner = n;

    }

    public Brok(int t) {

	    teller = t;

	    nevner = 1;

    }

    public int getNevner() {

	    return nevner;

    }

    public int getTeller() {

	    return teller;

    }

    public void multipliser(int nyTeller, int nyNevner){

	    this.nevner = nevner * nyNevner;
	    this.teller = teller * nyTeller;  

    }

}




Main-klassen: 



class brokTest {
	public static void main(String[] args) {

		Brok brok1 = new Brok(5,2); 
		brok1.multipliser(5,2); 
		int nevner  = brok1.getNevner();
		int teller = brok1.getTeller();  
		System.out.println("Resultat: " + teller + "/" + nevner ); 
	}
}

Dette gikk jo, men er det greit å ha 2 parametere i multipliser-metoden? Jeg ser du bruker kun en parameter "int number" i den første metoden din. Tror det er der jeg faller ut.

 

Jeg har en kontruktør som inneholder en parameter for nevner, og en for teller. Denne skal ganges med en annen brøk som har nevner og teller, da finner jeg ingen andre plasser å hente brøk nummer 2 fra enn utregningsmetoden :)

Endret av BloodySquito
Lenke til kommentar

Jeg laget to multiply()-metoder, en for å gange brøken med et heltall, og en for å gange brøken med en annen brøk (den første metoden gjør det bare litt greiere å gange brøken med et heltall, man hadde jo oppnådd det samme med "fraction.multiply(new Fraction(number));").

 

Når du først har laget en Brok-klasse, synes jeg du bør bruke den som parameter når du skal gange to brøker med hverandre, slik som jeg gjorde. Se litt nærmere på koden, så ser du hvordan du kan gjøre det.

Lenke til kommentar

 

 

Når du først har laget en Brok-klasse, synes jeg du bør bruke den som parameter når du skal gange to brøker med hverandre, slik som jeg gjorde. Se litt nærmere på koden, så ser du hvordan du kan gjøre det.

 

Jeg skal se på det! Det kommer nok sikkert i et av de nærmeste kapitlene i boken også.

Uansett,takk for hjelpen!

Lenke til kommentar

Jeg kom til slutt i mål med oppgaven, men det er nok en god del ting som kan/bør endres, men jeg fikk i hvertfall riktig resultat på de testene jeg kjørte.

Poster slutt-resultatet mitt her:

 

Brok-klassen:

 

 

public class Brok {

    private int teller;
    private int nevner;

    public Brok(int t, int n) {
	    if (n == 0) {
		    throw new IllegalArgumentException("Nevner kan ikke være 0");
	    }

	    this.teller = t;
	    this.nevner = n;
    }

    public Brok(int t) {
	    teller = t;
	    nevner = 1;
    }

    public int getNevner() {
	    return nevner;
    }

    public int getTeller() {
	    return teller;
    }

    public void multipliser(int teller, int nevner){
	    this.nevner = this.nevner * nevner;
	    this.teller = this.teller * teller;  
    }

    public void adder(int teller, int nevner) {
    	if(this.nevner != nevner) { 
    		this.teller = this.teller * nevner + this.nevner*teller; 
    		this.nevner = this.nevner*nevner; 
    	}
    	else {
    		this.nevner = nevner;
    		this.teller += teller; 
    	}
    }

    public void divider(int teller, int nevner) {
    	this.teller *= nevner; 
    	this.nevner *= teller; 
    }

    public void substraher(int teller, int nevner) {
    	if(this.nevner != nevner) { 
    		this.teller = this.teller * nevner - this.nevner*teller; 
    		this.nevner = this.nevner*nevner; 
    	}
    	else {
    		this.nevner = nevner;
    		this.teller -= teller; 
    	}
    }

    public void forkort() {               
    	if(teller > nevner) {    //Finner ut om teller eller nevner er størst
    		for(int i = nevner; i > 0; i--) {
    			if(nevner % i == 0 && teller % i == 0) {
                     this.nevner = this.nevner / i; 
                     this.teller = this.teller / i; 
                      }
                     }
                    }
                 else {
                 	for(int i = teller; i > 0; i--) {
    			if(teller % i == 0 && nevner % i == 0) {
                     this.nevner = this.nevner / i; 
                     this.teller = this.teller / i; 
                  }
                 }
    			}
    		   }
    	      } 	

 

 

 

Main-klassen: (InterruptedException var bare noe jeg testet ut fra noen oppgaver jeg så senere i boken).

 

 



class brokTest {
	public static void main(String[] args) throws InterruptedException {
		Brok brok1 = new Brok(5,2); 
		Brok brok2 = new Brok(4,2); 
		Brok brok3 = new Brok(8,4); 
		Brok brok4 = new Brok(18,2); 

		brok1.multipliser(5,2); 
		brok1.forkort(); 
		brok2.adder(6,2);
		brok2.forkort(); 
		brok3.divider(12,4); 
		brok3.forkort(); 
		brok4.substraher(6,4); 
		brok4.forkort(); 
        
        Thread.currentThread().sleep(2000); 
		System.out.println("Antall tester: 4"); 
        Thread.currentThread().sleep(1500); 
		if(brok1.getNevner() == 4 && brok1.getTeller() == 25){
			System.out.println("Test 1: Multiplisering Vellykket"); 
		}
		else {
			System.out.println("Test 1: Misslykket\n\nTeller(4) ble " + brok1.getTeller() + "\nNevner(25) ble " + brok1.getNevner()); 
		}
		Thread.currentThread().sleep(1500);

		if(brok2.getNevner() == 1 && brok2.getTeller() == 5) {
			System.out.println("Test 2: Addering Vellykket"); 
		}
		else {
			System.out.println("Test 2: Addering misslykket\n\nTeller(5) ble " + brok2.getTeller() + "\nNevner(1) ble " + brok2.getNevner()); 
		}
		Thread.currentThread().sleep(1500);

		if(brok3.getTeller() == 2 && brok3.getNevner() == 3) {
			System.out.println("Test 3: Dividering Vellykket"); 
		}
		else {
			System.out.println("Test 3: Dividering misslykket:\n\nTeller(2) ble " + brok3.getTeller() + "\nNevner(3) ble " + brok3.getNevner()); 
		}
		Thread.currentThread().sleep(1500);
		if(brok4.getTeller() == 15 && brok4.getNevner() == 2) {
			System.out.println("Test 4: Substrahering vellykket"); 
		}
		else {
			System.out.println("Test 4: Substrahering misslykket:\n\nTeller(15) ble " + brok4.getTeller() + "\nNevner(2) ble " + brok4.getNevner()); 
		}
	}
}

 

 

 

Da jeg prøvde å bruke konstruktøren som parameter på utregnings-metodene fikk jeg en kompileringsfeil.

 public void multipliser(Brok brok){
	    this.nevner = this.nevner * brok.nevner;
	    this.teller = this.teller * brok.teller;  
    }

Dette gav denne kompileringsfeilen: 

java:10: error: method multipliser in class Brok cannot be applied to given types: brok1.multipliser(5,2); 

Required: Brok
found: int, int
reason: actual and formal argument lists differ in lenght
1 error 
Lenke til kommentar

Litt usikker på hva du mener når du sier at du prøvde konstruktøren, men du kan ikke skrive

 

 

brok1.multipliser(5,2);

 

når metoden er

 

 

public void multipliser(Brok brok){

 

Du har skrevet at du skal ta inn en brøk, så da må du lage en brøk og sette inn det.

Lenke til kommentar

Noe slikt:

Brok en = new Brok(1, 2);
Brok to = new Brok(2);
en.multipliser(to);

Det kan kanskje se mer tungvint ut enn denne koden:

Brok en = new Brok(1, 2);
en.multipliser(2, 1);

Men tanken er at når du bruker brøk-klassen aktivt, vil du ha flere brøk-objekter du vil regne med, da ser du fort hva som ser best ut:

Brok x = ...; Brok y = ...;
...
x.multipliser(y);
// vs
x.multipliser(y.getTeller(), y.getNevner());

Med koden min (der brøk-objektene ikke kan endres etter de er opprettet) hadde det forøvrig blitt noe slikt:

Factor oneHalf = new Factor(1, 2);
Factor two = new Factor(2);
Factor one = oneHalf.multiply(two);
Endret av jonny
Lenke til kommentar

 

Noe slikt:

Brok en = new Brok(1, 2);
Brok to = new Brok(2);
en.multipliser(to);

Med koden min (der brøk-objektene ikke kan endres etter de er opprettet) hadde det blitt noe slikt:

Factor oneHalf = new Factor(1, 2);
Factor two = new Factor(2);
Factor one = oneHalf.multiply(two);

 

Takk! Det gjorde koden min en god del ryddigere og lettere å lese!

Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
×
×
  • Opprett ny...