Toon posts:

Java: while opdracht met een && operator

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik ben bezig om Java te leren, maar soms loop ik tegen een simpel probleem aan waarbij ik met de boeken en regels erbij niet zie wat ik fout doe. Zo wil ik bijvoorbeeld een while opdracht schrijven met 2 boolean vergelijkingen waarbij in beide vergelijkingen de waarde niet 0 mag zijn. Ik schrijf dan dit:

code:
1
while (teller % t != 0 && noemer % t != 0){


En mijn code wordt dan ook niet altijd goed uitgevoerd.
Ik weet inmiddels dat dit wel werkt:

code:
1
while (!(teller % t == 0 && noemer % t == 0)){


Maar zie niet waarom mijn eerste manier niet goed is.

Beste antwoord (via Verwijderd op 22-04-2016 10:33)


  • Robbiedobbie
  • Registratie: Augustus 2009
  • Laatst online: 11-10 13:26
Ik denk dat je boolean logica niet helemaal begrijpt.
Bijv, !a && !b evalueert alleen naar true als zowel a als b false zijn.

Je 2e statement zegt !(a && b), welke true is wanneer a, en/of b false is.

Als je dit heel uitgebreid wil leren, kun je het beste kijken naar Propositielogica

[ Voor 7% gewijzigd door Robbiedobbie op 22-04-2016 10:13 ]

Alle reacties


Acties:
  • 0 Henk 'm!

  • Cor453
  • Registratie: Mei 2011
  • Laatst online: 05-10 14:53
Wat bedoel je met "niet goed uitgevoerd"? Post eens een volledig voorbeeld, maakt makkelijker kijken.

Acties:
  • 0 Henk 'm!

  • Merethil
  • Registratie: December 2008
  • Laatst online: 11-10 20:24
Verwijderd schreef op vrijdag 22 april 2016 @ 09:53:
Ik ben bezig om Java te leren, maar soms loop ik tegen een simpel probleem aan waarbij ik met de boeken en regels erbij niet zie wat ik fout doe. Zo wil ik bijvoorbeeld een while opdracht schrijven met 2 boolean vergelijkingen waarbij in beide vergelijkingen de waarde niet 0 mag zijn. Ik schrijf dan dit:

code:
1
while (teller % t != 0 && noemer % t != 0){


En mijn code wordt dan ook niet altijd goed uitgevoerd.
Ik weet inmiddels dat dit wel werkt:

code:
1
while (!(teller % t == 0 && noemer % t == 0)){


Maar zie niet waarom mijn eerste manier niet goed is.
Maakt het verschil als je de eerste test de twee vergelijkingen binnen haakjes zet? Ik heb het net even uitgeprobeerd lokaal maar allebei de oplossingen lijken bij mij hetzelfde te doen, zoals verwacht.
Cor453 schreef op vrijdag 22 april 2016 @ 10:01:
Wat bedoel je met "niet goed uitgevoerd"? Post eens een volledig voorbeeld, maakt makkelijker kijken.
Dit, maar dan wel met zo min mogelijk nutteloze code. Even een testcase die gewoon misgaat voor jou, waarbij we iets meer zien dan alleen de while-vergelijkingen.





Robbiedobbie heeft gelijk hier, er zit natuurlijk verschil tussen statement 1 en statement 2; ik had 't alleen getest met een teller en noemer die gelijk bleven een een vaste "t" van 5, waardoor ze bij mij exact 'tzelfde deden :+

[ Voor 25% gewijzigd door Merethil op 22-04-2016 10:18 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
De bedoeling van deze oefening is om de grootste gemeenschappelijke deler van een breuk te krijgen. De gehele methode is zo geschreven:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  /*
   * Vereenvoudigt de breuk door teller en noemer
   * te delen door hun grootste gemene deler
   */
  public void vereenvoudig() {
    if (teller == 0){
      noemer = 1;
    }
    
    
    long t;
    if (teller > noemer){
      t = noemer;
    }
      else{
        t = teller;
      }
 
      while (!(teller % t == 0 && noemer % t == 0)){
        t--;
      }
      teller = teller / t;
      noemer = noemer / t;
    
    }
    
  }


wanneer ik mijn eerste code laat staan, wordt bij sommige breuken op de juiste manier de ggd gevonden en wordt de eenvoudigste breuk teruggegeven. Maar bij 21/18 bijvoorbeeld wordt 1/1 teruggegeven, dit klopt niet dat zou 7/6 moeten zijn. Dit probleem werd meteen verholpen bij de aanpassing die ik in mijn openingspost liet zien.

Acties:
  • Beste antwoord
  • +3 Henk 'm!

  • Robbiedobbie
  • Registratie: Augustus 2009
  • Laatst online: 11-10 13:26
Ik denk dat je boolean logica niet helemaal begrijpt.
Bijv, !a && !b evalueert alleen naar true als zowel a als b false zijn.

Je 2e statement zegt !(a && b), welke true is wanneer a, en/of b false is.

Als je dit heel uitgebreid wil leren, kun je het beste kijken naar Propositielogica

[ Voor 7% gewijzigd door Robbiedobbie op 22-04-2016 10:13 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik zie het :F , dank voor het reageren!

[ Voor 6% gewijzigd door Verwijderd op 22-04-2016 10:39 ]


Acties:
  • 0 Henk 'm!

  • Edwin88
  • Registratie: Januari 2005
  • Laatst online: 03-10 23:05
Tip: leer jezelf aan al je variabelen en comments in het Engels te doen. Dan beperk je je niet tot de Nederlandse developer circles en kan je ook bijvoorbeeld makkelijker ooit je code op github kwijt en meedoen aan internationale fora.

En; voorzie je code van meer comments! Zo kan je, over 5 jaar, weer in 1 oogopslag zien wat je doet in je code. Je hoeft niet alles te commenteren, maar wel meer dan je nu doet. Er komt een tijd dat je niet de enige bent die aan een codebase werkt.

Kleine moeite nu, maar als je je dat eenmaal aanleert is je werk een stuk makkelijker later.

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Edwin88 schreef op vrijdag 22 april 2016 @ 10:55:
En; voorzie je code van meer comments! Zo kan je, over 5 jaar, weer in 1 oogopslag zien wat je doet in je code. Je hoeft niet alles te commenteren, maar wel meer dan je nu doet. Er komt een tijd dat je niet de enige bent die aan een codebase werkt.
Wat zou je in dit stukje dan nog willen commenten? Er staat duidelijk boven de functie wat 'ie doet en de regels zijn eenvoudig genoeg om te doorgronden. De functie is bovendien dermate kort dat hij samen met het commentaar in één scherm past zonder scrollen. Elk stukje commentaar dat je toevoegt lijkt mij tijdverspilling. ;)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • Raynman
  • Registratie: Augustus 2004
  • Laatst online: 01:15
En het kan nog wel wat korter en duidelijker door
Java:
1
long t = Math.min(teller, noemer);
te gebruiken i.p.v. die if/else.

Acties:
  • 0 Henk 'm!

  • Edwin88
  • Registratie: Januari 2005
  • Laatst online: 03-10 23:05
NMe schreef op vrijdag 22 april 2016 @ 11:18:
[...]

Wat zou je in dit stukje dan nog willen commenten? Er staat duidelijk boven de functie wat 'ie doet en de regels zijn eenvoudig genoeg om te doorgronden. De functie is bovendien dermate kort dat hij samen met het commentaar in één scherm past zonder scrollen. Elk stukje commentaar dat je toevoegt lijkt mij tijdverspilling. ;)
Ik bedoel dan ook een of twee one-liners die je nodeloos uitpluis werk kunnen besparen. De functie is inderdaad simpel genoeg om zelf te doorgronden, maar kan met 1 of 2 regeltjes net even sneller te scannen zijn.

Bijvoorbeeld variabele t -> je moet even bedenken hoe het ook alweer zit voordat je beseft dat het om de deler gaat.

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/*
   * Vereenvoudigt de breuk door teller en noemer
   * te delen door hun grootste gemene deler
   */
  public void vereenvoudig() {
    if (teller == 0){
      noemer = 1;
    }
    
    // bepaal of de noemer of teller de deler (t) word
    long t;
    if (teller > noemer){
      t = noemer;
    }
      else{
        t = teller;
      }
 
    // verminder de deler tot bij beide het restgetal 0 is
      while (!(teller % t == 0 && noemer % t == 0)){
        t--;
      }
      teller = teller / t;
      noemer = noemer / t;
    
    }
  }


Wat vaak ook goed werkt voor een beginnend programmeur is eerst comments schrijven, zodat je de structuur van je code al vormgeeft. Hierna implementeer je de code. Net als professionele programmeurs alles via TDD doen: eerst definieer je wat je gaat maken waarna je het pas gaat doen.

Maar, uiteindelijk is dit natuurlijk ook persoonlijke voorkeur en afhankelijk van de complexiteit van de code.

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Commentaar dat niet meer doet dan letterlijk uitschrijven wat de code betekent is zinloos als de code zo simpel is als deze, dat vertelt de code je immers al. Goed commentaar vertelt je in grote lijnen wat de functie doet of per blokje dat ingewikkeld genoeg is voor meer uitleg eventueel hoe de code werkt. Het meest zinnige commentaar legt bovendien eerder uit waarom iets op een bepaalde manier geschreven is.

Met de alinea onder het codeblok ben ik het wel eens: eerst uitschrijven in commentaar hoe je de functie aan gaat pakken kan heel zinnig zijn. Op dezelfde manier kan het heel zinnig zijn om eerst de functie-calls te schrijven in de context waar ze nodig zijn ("zó wil ik deze code gaan gebruiken") en pas daarna de functies zelf.

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik heb zeker iets aan deze tips. Merk dat ik vaak te snel enthousiast aan de slag ga, en geneigd ben het ontwerp in mijn hoofd te maken i.p.v. uit te schrijven. Ik wil de basis goed onder de knie krijgen, en ga dus ook beter op mijn comments letten. Bedankt allemaal!

Acties:
  • 0 Henk 'm!

  • Raynman
  • Registratie: Augustus 2004
  • Laatst online: 01:15
Edwin88 schreef op vrijdag 22 april 2016 @ 11:38:

Bijvoorbeeld variabele t -> je moet even bedenken hoe het ook alweer zit voordat je beseft dat het om de deler gaat.
Noem de variable dan gewoon 'deler' i.p.v. 't'... De code maakt dan duidelijk dat je "bepaal[t] of de noemer of teller de deler wordT". Commentaar zou hoogstens kort kunnen uitleggen waarom de kleinste van de twee gekozen wordt, als je dat nodig acht.

Acties:
  • 0 Henk 'm!

  • Edwin88
  • Registratie: Januari 2005
  • Laatst online: 03-10 23:05
Raynman schreef op vrijdag 22 april 2016 @ 14:24:
[...]
Noem de variable dan gewoon 'deler' i.p.v. 't'... De code maakt dan duidelijk dat je "bepaal[t] of de noemer of teller de deler wordT". Commentaar zou hoogstens kort kunnen uitleggen waarom de kleinste van de twee gekozen wordt, als je dat nodig acht.
ik gebruikte de code van OP als voorbeeld, vandaar dat ik geen variabelen heb aangepast.


Verder vind ik het zelf prettig om in stukken code te scannen naar de comments die, heel kort, uitleggen wat het volgende stuk code doet. Zo kan je snel een stukje functionaliteit vinden. In dit korte stukje code breek je het algoritme op in 2-3 stappen, waarbij je elke stap kort (1 zin max!) neerzet wat het doet.

Mocht je dan iets willen aanpassen, dan is dat meestal binnen een stuk functionaliteit. Via die comments vind je het dan snel terug.

Het is een persoonlijke style, maar ik heb bijvoorbeeld geen zin om meer dan 10 regels code te moeten herlezen om te ontdekken wat het doet. Daar zijn de comments immers voor. De een heeft wat minder nodig dan de ander. Ook simpele code kan prima comments gebruiken -> je moet inderdaad niet doorslaan en meer comments dan code hebben.

Acties:
  • 0 Henk 'm!

  • frank87
  • Registratie: Januari 2014
  • Laatst online: 13-05 23:06
De code gaat ook mis als de teller 0 is: t wordt 0, en daar ga je door delen (Hoewel ik niet zeker weet of x%0 niet per ongeluk x oplevert, waardoor de.noemer uiteindelijk -1 wordt). Ik denk dat daar een return mist.

Er is een snellere manier is om de grootst gemene deler te vinden:
Voor twee positieve gehele getallen (a < b) geldt:
GGD(a, b) = a of GGD(a,b) = GGD( a, b - a )

dus dan krijg je:
a = min( teller, noemer);
b = max( teller, noemer);

while ( b % a != 0 ) {
int c = b%a;
b=a;
a=c;
}

ggd = a

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22:33

.oisyn

Moderator Devschuur®

Demotivational Speaker

frank87 schreef op dinsdag 26 april 2016 @ 00:24:
(Hoewel ik niet zeker weet of x%0 niet per ongeluk x oplevert, waardoor de.noemer uiteindelijk -1 wordt)
Dat kan niet, want je kunt niet door 0 delen. Het zal dan ook een DivisionByZeroException opleveren.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • frank87
  • Registratie: Januari 2014
  • Laatst online: 13-05 23:06
@.oisyn
Ik had ook duidelijker moeten zijn waar die return had moeten staan:
if ( teller == 0 ) { noemer = 1; return }
Pagina: 1