# Schaltjahr



## thor_norsk (15. Aug 2021)

Guten Tag,

Schreiben Sie ein Programm, das eine Jahreszahl über einen grafischen Eingabedialog abfragt und dann ausgibt, ob das Jahr ein Schaltjahr ist.
Die Überprüfung können Sie mit folgenden Regeln durchführen:
Ein Jahr ist kein Schaltjahr, wenn die Jahreszahl nicht durch 4 teilbar ist.
Ein Jahr ist ein Schaltjahr, wenn die Jahreszahl durch 4, aber nicht durch 100 teilbar ist.
Es ist ebenfalls ein Schaltjahr, wenn die Jahreszahl gleichzeitig durch 4, durch 100 und durch 400 teilbar ist.
Ein Beispiel:
Das Jahr 1964 war ein Schaltjahr. Die Jahreszahl lässt sich durch 4, aber nicht durch 100 teilen.
Das Jahr 1900 war kein Schaltjahr. Die Jahreszahl lässt sich zwar durch 4 und auch durch 100 teilen, aber nicht durch 400.
Sie können für die Überprüfung der Teilbarkeit den Modulo-Operator % und if … else-Verzweigungen benutzen. Zur Erinnerung: Wenn eine Zahl x nicht glatt durch y teilbar ist, dann liefert der Ausdruck (x % y) einen Wert größer als 0.
Setzen Sie bei der Überprüfung der Teilbarkeit eine weitere Variable ein, die markiert, ob das Jahr ein Schaltjahr ist oder nicht. Werten Sie diese Variable am Ende des Programms aus und lassen Sie dann auf dem Bildschirm ausgeben, ob es sich um ein Schaltjahr handelt oder nicht.

Meine Lösung:

import javax.swing.*;

public class Schaltjahr {

    public static void main(String[] args) {

        int eingabe;
        int zahl1 = 4;
        int zahl2 = 100;
        int zahl3 = 400;

        eingabe = Integer.parseInt(JOptionPane.showInputDialog("Bitte geben Sie ein Jahr ein:"));

        if( (eingabe % zahl1 ==0) && (eingabe % zahl2 !=0) || (eingabe % zahl1 == 0) && (eingabe % zahl2 == 0) && (eingabe % zahl3 == 0 ) ) {
            System.out.println("Es ist ein Schaltjahr");
            }
        else {
            System.out.println("Ihre Eingabe ist kein Schaltjahr!");
        }
    }
}

Es funktioniert, aber ich habe mir andere Bespiele angeschaut, die haben if - Verzweigung verschachtelt und eine boolesche Variable ins Spiel gebracht.

Danke!


----------



## mrBrown (15. Aug 2021)

Was ist denn deine Frage?


----------



## M.L. (15. Aug 2021)

Bei der Berechnung eines "leap year" kann es ja auch mehrere Wege zum Ziel geben: https://beginnersbook.com/2017/09/java-program-to-check-leap-year/  (oder i.V. mit der neuen Datetime API: https://www.baeldung.com/java-8-date-time-intro )


----------



## thor_norsk (15. Aug 2021)

Habe ich die Aufgabe richtig gelöst? Oder erkennt ihr einen Fehler?


----------



## mihe7 (15. Aug 2021)

Es sollte korrekt funktionieren. 

Wenn Du meinst, Variablen (hier wären Konstanten angebracht) für fixe Zahlen einführen zu müssen, dann sollten die auch passende Namen und nicht zahl1, zahl2, zahl3 haben. 

Und dann wäre die Frage, welche Zahl sich durch 400 aber nicht durch 4 oder 100 teilen lässt...


----------



## Blender3D (16. Aug 2021)

[CODE lang="java" highlight="5-7"]import javax.swing.JOptionPane;

public class TestLeapYear {
    public static void main(String[] args) {
        int year = inputYear("Geben Sie eine Jahreszahl ein: ", 1900, 2999);
        String message = year + " ist " + (isLeapYear(year) ? "" : "k") + "ein Schaltjahr!";
        JOptionPane.showMessageDialog(null, message);
    }

    public static int inputYear(String text, int min, int max) {
        int jahr = min;
        boolean ok = false;
        do {
            String eingabe = JOptionPane.showInputDialog(text, min + "");
            try {
                jahr = Integer.parseInt(eingabe);
                if (jahr < min || jahr > max)
                    JOptionPane.showMessageDialog(null, "Der Bereich für gültige Jahre ist [" + min + "-" + max + "]");
                else
                    ok = true;
            } catch (NumberFormatException e) {
                JOptionPane.showMessageDialog(null, "Bitte nur Zahlen eingeben!");
            }
        } while (!ok);
        return jahr;
    }

    public static boolean isLeapYear(int year) {
        return (year % 4 == 0 && year % 100 != 0 || year % 400 == 0);
    }
}[/CODE]


----------



## thor_norsk (17. Aug 2021)

Guten Abend,
ich habe über meine Fallunterscheidungen nachgedacht und andere Variante programmiert! Hätte gerne gewusst, ob ich richtig programmiert habe? 


package schaltjahr;
import javax.swing.*;

public class Schaltjahr {

    public static boolean Schaltjahr(int jahr) {
        if (jahr % 400 == 0) {
            return true;
        }
        else if (jahr % 100 == 0) {
            return false;
        }
        else if (jahr % 4 == 0) {
            return true;
        } 
        else {
            return false;
        }
    }

    public static void main(String[] args) {

        int eingabe;
        eingabe = Integer.parseInt(JOptionPane.showInputDialog("Bitte geben Sie ein Jahr ein:"));

        if (Schaltjahr(eingabe)) {
            System.out.println("Schaltjahr!");
        } 
        else {
            System.out.println("Kein Schaltjahr!");
        }
    }
}


----------



## Blender3D (18. Aug 2021)

thor_norsk hat gesagt.:


> Hätte gerne gewusst, ob ich richtig programmiert habe?


*Ist richtig.*
[CODE lang="java" title="Deine Variante"]public static boolean Schaltjahr(int jahr) {
    if (jahr % 400 == 0) {
        return true;
    }else if (jahr % 100 == 0) {
        return false;
    }else if (jahr % 4 == 0) {
        return true;
    }else {
        return false;
    }
}[/CODE]
*Mach aber das selbe wie das *

```
public static boolean isLeapYear(int year) {
        return (year % 4 == 0 && year % 100 != 0 || year % 400 == 0);
    }
```

Vergleiche den Code und überlege welcher von beiden übersichtlicher ist.


----------



## LimDul (18. Aug 2021)

Blender3D hat gesagt.:


> *Ist richtig.*
> [CODE lang="java" title="Deine Variante"]public static boolean Schaltjahr(int jahr) {
> if (jahr % 400 == 0) {
> return true;
> ...


Die erste Variante find ich besser als die zweite. Ich bin überhaupt kein Freund davon && und || zu mischen ohne Klammern zu setzen. Das heißt, wenn die zweite Variante, dann so:


```
return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);
```

Sie sind aber alle signifikant besser als das aus dem ersten Beitrag aus folgenden Gründen:

*Eigene Methode*
Eine eigene Methode erlaubt es mit Unit-Tests diese Funktionalität einfach zu testen. Das heißt insbesondere, dass im restlichen Code man nicht mehr die Logik verstehen muss, was der Block macht, sondern man am Methodenaufruf das bereits sieht.

*Verzicht auf unötige, schlecht benannte Variablen*
Durch den Verzicht auf die Hilfsvariablen zahl1, zahl2 und zahl3 ist der Code lesbar ohne das man dauernd zwischen verschiedenen Zeilen springen muss um ihn zu verstehen.


Was noch zu korrigieren wäre:
* Methoden fangen immer mit einem Kleinbuchstaben an
* Methoden mit einem boolean Rückgabewert sollte man - sofern sinnvoll - mit dem Präfix is benennen (und dann Camel-Case).

Sprich der richtige Name wäre "isSchaltjahr".


----------



## mihe7 (18. Aug 2021)

@LimDul, ich würde noch den Verzicht auf unnötige Prüfungen anführen.


----------



## Blender3D (18. Aug 2021)

LimDul hat gesagt.:


> Die erste Variante find ich besser als die zweite. Ich bin überhaupt kein Freund davon && und || zu mischen ohne Klammern zu setzen. Das heißt, wenn die zweite Variante, dann so:


Das ist in Java in durch die Priorität geregelt. && (Priorität 10)  || (Priorität 11) % (Priorität 2)
Insofern sind hier Klammern nicht nötig.
Eine solche Funktion wird normalerweise nicht mehr verändert sondern nur mehr benutzt. Daher ist kein eigener Test dafür notwendig.


----------



## LimDul (18. Aug 2021)

Blender3D hat gesagt.:


> Das ist in Java in durch die Priorität geregelt. && (Priorität 10)  || (Priorität 11) % (Priorität 2)
> Insofern sind hier Klammern nicht nötig.


Technisch nicht - zum Verständnis schon. Ja, es keine Änderung der Funktionlität. Aber es macht den Code um längen lesbarer. Auch wenn man es Wissen sollte, das && vor || gilt - Code sollte so einfach lesbar wie möglich sein und da gehören Klammern meines Erachtens dazu



Blender3D hat gesagt.:


> Eine solche Funktion wird normalerweise nicht mehr verändert sondern nur mehr benutzt. Daher ist kein eigener Test dafür notwendig.


Was ist den das für ein Unfug? Was ich nicht ändere muss ich nicht testen?

Das ist doch genau der Sinn von Unit-Tests - Sicherstellen, dass es sich nicht ändert!

Ich würde so einen Code ohne Unit-Test auch immer im Code Review zurückweisen. Das ist Funktionalität die über ein get hinaus geht- damit müssen dafür Unit-Tests  geschrieben werden, wenn möglich. Und die kosten hier keine 5 Minuten.


----------



## thor_norsk (18. Aug 2021)

Guten Abend, vielen Dank!


----------



## Michelangelo (25. Jan 2022)

thor_norsk hat gesagt.:


> Guten Tag,
> 
> Schreiben Sie ein Programm, das eine Jahreszahl über einen grafischen Eingabedialog abfragt und dann ausgibt, ob das Jahr ein Schaltjahr ist.
> Die Überprüfung können Sie mit folgenden Regeln durchführen:
> ...


Hallo, habe da mal eine Frage.... wie hast den Teil von:"" Setzen Sie bei der Überprüfung der Teilbarkeit eine weitere Variable ein, die markiert, ob das Schaltjahr...................- ganz zu Schluss der Aufgabenstellung?! Hast du es hinbekommen? MFG


----------



## thor_norsk (25. Jan 2022)

Guten Abend,
Bedingung für Schaltjahr ist vorgegeben. Die boolesche Methode überprüft Alle Fälle und liefert das Ergebnis zurück .
Oder habe ich dich falsch verstanden?


----------



## Michelangelo (25. Jan 2022)

thor_norsk hat gesagt.:


> Guten Abend,
> Bedingung für Schaltjahr ist vorgegeben. Die boolesche Methode überprüft Alle Fälle und liefert das Ergebnis zurück .
> Oder habe ich dich falsch verstanden?


Guten Morgen,
Aus der Aufgabenstellung geht hervor daß man eine weitere variable zur Überprüfung und Markierung des Schaltjahres verwenden soll welche zum Schluss mit ausgegeben werden soll. Letzter Absatz in der Aufgabenstellung.
 Hattest du für die Aufgabe volle Punktzahl bekommen?
Liebe Grüße


----------



## Mart (25. Jan 2022)

```
boolean sinnLoseZwischenVariable  = isLeapYear(1942);
System.out.println(sinnLoseZwischenVariable);
```
das?


----------



## Michelangelo (25. Jan 2022)

thor_norsk hat gesagt.:


> Guten Abend,
> Bedingung für Schaltjahr ist vorgegeben. Die boolesche Methode überprüft Alle Fälle und liefert das Ergebnis zurück .
> Oder habe ich dich falsch verstanden?


Guten morgen, aus der Aufgabenstellung geht hervor,daß man eine weitere variable einsetzen soll zur Überprüfung und Markierung. Diese soll zum Schluss auch ausgegeben werden( letzter Absatz in der Aufgabenstellung). Wie viele Punkte hast du für diese Aufgabe bekommen? Ich mache den selben Lehrgang🤓.
Liebe Grüße


----------



## Michelangelo (25. Jan 2022)

Mart hat gesagt.:


> ```
> boolean sinnLoseZwischenVariable  = isLeapYear(1942);
> System.out.println(sinnLoseZwischenVariable);
> ```
> das?


Sieht nicht so aus als wenn etwas hier durch eine WEITERE VARIABLE markiert werden würde...


----------



## mihe7 (25. Jan 2022)

Ich vermute mal, es ist sowas in der Richung gemeint:

```
boolean schaltjahr = (jahr % 4 == 0);
schaltjahr = schaltjahr && (jahr % 100 != 0);
schaltjahr = schaltjahr || (jahr % 400 = 0);

if (schaltjahr) {
     System.out.println("%d ist ein Schaltjahr%n", jahr);
} else {
     System.out.println("%d ist kein Schaltjahr%n", jahr);
}
```


----------

