Java Lässt sich folgendes Snippet vereinfachen?

CyborgBeta

Lt. Commander
Registriert
Jan. 2021
Beiträge
1.831
Manchmal sieht man ja die einfachsten Sachen nicht ... Falls ja, bitte die Zeilennummer angeben und begründen.

Java:
    public static void main(String[] args) {
        double base = 0.0633;
        int pieces = 20;
        for (int i = 1; i <= 20; i++) {
            double inter = 0.05 * i;
            double l = (-inter / 100.0 * (pieces / 2.0) + 1.0) * base;
            double u = (inter / 100.0 * (pieces / 2.0) + 1.0) * base;
            System.out.printf("inter = %f%n", inter);
            System.out.printf("l     = %f%n", l);
            System.out.printf("u     = %f%n", u);
            System.out.println("---");
        }
    }

Ich habe Zeile 6 und 7 in Verdacht.
 
Java:
public static void main(String[] a) {
    double b=0.0633, i, p=20;
    for (i = 1; i <= p; i++) {
        double t = 0.05 * i, x = t / 100 * (p / 2.0);
        System.out.printf("inter = %f%nl     = %f%nu     = %f%n---%n", t, (1-x)*b, (1+x)*b);
    }
}

CyborgBeta schrieb:
Manchmal sieht man ja die einfachsten Sachen nicht ... Falls ja, bitte die Zeilennummer angeben und begründen.
das klingt irgendwie boese nach hausaufgabe

aber grob so. bin gerade untwerwegs
 
ich bin jetzt nicht der java oder mathe experte, aber double inter,l,u kann man doch außerhalb der schleife erzeugen.
u und l ist das gleiche bis auf das minus oder?
ist dann u = -u = l
 
madmax2010 schrieb:
Jetzt geht das wieder los :rolleyes: es hat dich keiner gebeten, zu antworten
Ergänzung ()

madmax2010 schrieb:
Java:
public static void main(String[] a) {
    double b=0.0633, i, p=20;
    for (i = 1; i <= p; i++) {
        double t = 0.05 * i, x = t / 100 * (p / 2.0);
        System.out.printf("inter = %f%nl     = %f%nu     = %f%n---%n", t, (1-x)*b, (1+x)*b);
    }
}


das klingt irgendwie boese nach hausaufgabe

aber grob so. bin gerade untwerwegs

1. keine Mehrfachdeklarationen in einer Zeile
2. i wird nur innerhalb der Schleife gebraucht
3. i muss ganzzahlig sein
4. p muss ganzzahlig sein
5. p und der upper bound sind nur zufällig identisch
6. 100 ist keine double-Literal
7. nicht mehr als ein Argument pro Ausgabe
 
Zuletzt bearbeitet:
Man könnte die Rechung in eine Methode auslagern. Macht sogar die IDE wenn man sie richtig bedient...

Der Teil ist identisch: " / 100.0 * (pieces / 2.0) + 1.0) * base".

Code:
    private static final double BASE = 0.0633d;
    private static final int PIECES = 20;

    private static double magic(double value) {
        return (value / 100.0 * (PIECES / 2.0) + 1.0) * BASE;
    }

   public static void main(String[] args) {
        for (int i = 1; i <= PIECES; i++) { // 20 zufällig, oder soll das gleich wie pieces sein?
            double inter = 0.05 * i;
            double l = magic(-inter);
            double u = magic(inter);
            System.out.printf("inter = %f%n", inter);
            System.out.printf("l     = %f%n", l);
            System.out.printf("u     = %f%n", u);
            System.out.println("---");
        }
    }

Die Frage ist halt immer: Was bedeutet einfacher? Dem Code sieht man halt so oder so nicht an, was er machen soll - zumindest geht es mir so.

Ergänzung ()

StefanArbe schrieb:
ich bin jetzt nicht der java oder mathe experte, aber double inter,l,u kann man doch außerhalb der schleife erzeugen.
u und l ist das gleiche bis auf das minus oder?
das +1 ist das entscheidende:
double l = (-inter / 100.0 * (pieces / 2.0) + 1.0) * base;
und inter ändert sich doch mit jeder Iteration.
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: BeBur, CyborgBeta und madmax2010
tollertyp schrieb:
20 zufällig, oder soll das gleich wie pieces sein?
Zufall, pieces kann zum Beispiel auch 16 sein. Die 20 (upper bound) ist hingegen fest.

Gefällt mir gut, ist übersichtlich. Aber auch in deinem Code wird jede Teilberechnung jeweils zweimal berechnet pro Schleifendurchlauf.
 
  • Gefällt mir
Reaktionen: tollertyp
Richtig. Die Frage ist halt, was ist das Ziel?
Lesbarkeit?
Effizienz?

das hier braucht man eigentlich auch nur einmal berechnen und könnte es als Konstante rausziehen: PIECES / 2.0

Wenn die Ausgabe der Variable inter nicht notwendig wäre, würde sich da noch mehr optimieren lassen. Aber dann ändert sich halt das Verhalten

Edit:
Ach ja, wenn Upperbound = 20 zufällig denselben Wert wie pieces annehmen kann, würde es sich auch anbieten, das als Konstante rauszuziehen.
"Don't make me think" - beim Lesen kommt halt zwangsweise die Frage, ob die Werte einen Zusammenhang haben. Das ist einer der Gründe, warum man Magic Numbers vermeiden sollte.
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: CyborgBeta
Man könnte etwas Mathe anwenden:

Java:
double l = (((-inter / 100.0) * (pieces / 2.0)) + 1.0) * base;
double u = (((inter / 100.0) * (pieces / 2.0)) + 1.0) * base;

So sieht das ganze mit allen Klammern aus, daraus kann man nun folgendes machen indem man ausmultipliziert.

Java:
double l = ((-inter / 100.0) * (pieces / 2.0)) * base + base;
double u = ((inter / 100.0) * (pieces / 2.0)) * base + base;

Und jetzt den doppelten Teil auslagern (Klammern könnte man dann noch weglassen).

Java:
double x = ((inter / 100.0) * (pieces / 2.0)) * base;
double l = -x + base;
double u = x + base;

Ich hoffe ich hab da jetzt keinen Fehler drin. Bin am Handy.
 
  • Gefällt mir
Reaktionen: StefanArbe, tollertyp und CyborgBeta
So würde es auch gehen.
Ob das besser ist? Es kommt halt mit weniger Multiplikationen aus, aber ist es lesbarer?

Code:
private static final double BASE = 0.0633;
private static final int PIECES = 20;
private static final int UPPER_BOUND = 20;
private static final double INTER_INCREMENT = (1.0d / UPPER_BOUND);
private static final double DELTA_INCREMENT = INTER_INCREMENT * BASE * PIECES / 200.0d;

public static void main(String[] args) {
    double delta = 0;
    for (int i = 1; i <= UPPER_BOUND; i++) {
        delta += DELTA_INCREMENT;
        double l = BASE - delta;
        double u = BASE + delta;

        double inter = INTER_INCREMENT * i;
        printValues(inter, l, u);
    }
}

private static void printValues(double inter, double l, double u) {
    System.out.printf("inter = %f%n", inter);
    System.out.printf("l     = %f%n", l);
    System.out.printf("u     = %f%n", u);
    System.out.println("---");
}

@marcOcram: In die Richtung ging diese Optimierung auch.
Wenn alle am Handy so sorgfältig schreiben würden wie du... :-) (kein Sarkasmus)
 
Zuletzt bearbeitet:
Java:
public static void main(String[] args) {
    double base = 0.0633;
    int pieces = 20;
    double a = pieces * base / 200;
    double inter = 0.05;

    for (int i = 1; i <= 20; i++) {
        double l = -inter * a + base;
        double u = inter * a + base;
        System.out.printf("inter = %f%n", inter);
        System.out.printf("l     = %f%n", l);
        System.out.printf("u     = %f%n", u);
        System.out.println("---");
        inter += 0.05;
    }
}
 
  • Gefällt mir
Reaktionen: CyborgBeta
Java:
public static void main(String[] args) {
    run(0.0633, 20, 0.05);
}

public static void run(double base, int pieces, double interFix) {
    double a = base * pieces * interFix / 200;
    for (int i = 1; i <= 20; i++) {
        System.out.printf("inter = %f%n", i * interFix);
        System.out.printf("l     = %f%n", -i * a + base);
        System.out.printf("u     = %f%n", i * a + base);
        System.out.println("---");
    }
}

"interFix" (oder zuvor "inter") ist - wie von @tollertyp angemerkt - natürlich kein schöner Parametername und sollte entsprechend umbenannt werden. Ich habe es lediglich für die Nachvollziehbarkeit so genannt. Es lagert die in der Aufgabe genannten und für die Berechnung von "inter" benötigten "fixen" 0.05 in einen Methodenparameter aus. Ob sinnvoll oder nicht, hängt halt von der genauen Aufgabenstellung ab.
 
Zuletzt bearbeitet:
tollertyp schrieb:
Richtig. Die Frage ist halt, was ist das Ziel?
Lesbarkeit?
Effizienz?
Wenn möglich, und es sich nicht gegenseitig ausschließt, dann sollte beides erreicht werden ...

Falls eins das andere ausschließt ... was ich eigentlich nicht glaube, dann hat die Lesbarkeit/Übersichtlichkeit eine höhere Prio
 
SaschaHa schrieb:
System.out.printf("inter = %f%n", i * inter);
inter ist also i * inter?
Kein guter Stil so.

@CyborgBeta: Ich glaube die Unterschiede in der Effizienz kann man vielleicht messen, aber relevant dürften die kaum sein. Wenn es keine guten Gründe gibt für anderes, sollte immer die Lesbarkeit im Vordergrund stehen.
 
  • Gefällt mir
Reaktionen: CyborgBeta
marcOcram schrieb:
Man könnte etwas Mathe anwenden:

Java:
double l = (((-inter / 100.0) * (pieces / 2.0)) + 1.0) * base;
double u = (((inter / 100.0) * (pieces / 2.0)) + 1.0) * base;

So sieht das ganze mit allen Klammern aus, daraus kann man nun folgendes machen indem man ausmultipliziert.

Java:
double l = ((-inter / 100.0) * (pieces / 2.0)) * base + base;
double u = ((inter / 100.0) * (pieces / 2.0)) * base + base;

Und jetzt den doppelten Teil auslagern (Klammern könnte man dann noch weglassen).

Java:
double x = ((inter / 100.0) * (pieces / 2.0)) * base;
double l = -x + base;
double u = x + base;

Ich hoffe ich hab da jetzt keinen Fehler drin. Bin am Handy.
wenn du noch / durch * (+ entsprechende geänderte werte) ersetzt wird es auch von der performance nice
 
Hast du Messungen gemacht, wie viel besser die Performance wird?
Sollten solche Optimierungen nicht von der JVM gemacht werden?
 
tollertyp schrieb:
inter ist also i * inter?
Kein guter Stil so.
Ich hätte es auch umbenannt, wenn ich wüsste, was mit "inter" genau gemeint sein soll. Damit der TE es nachvollziehen kann, habe ich es erstmal so gelassen. Ändern kann (und sollte) er den Namen dann selbst.

Sofern es doch einen Zusammenhang zwischen den beiden 20 (Upperbound und pieces) und der 0.05 (= 1/20) geben sollte, würde ich persönlich es so machen:

Java:
public static void main(String[] args) {
    run(0.0633, 20);
}

public static void run(double base, int pieces) {
    double a = base / 200;
    for (int i = 1; i <= pieces; i++) {
        System.out.printf("inter = %f%n", (double) i / pieces);
        System.out.printf("l     = %f%n", -i * a + base);
        System.out.printf("u     = %f%n", i * a + base);
        System.out.println("---");
    }
}

Wie man sieht, würde sich in diesem Fall einiges rauskürzen. Jedenfalls finde ich die Werte bei der Aufgabe ziemlich ungünstig gewählt, falls wirklich kein Zusammenhang bestehen soll. Das sorgt nur unnötig für Verwirrung beim Kürzen.
 
  • Gefällt mir
Reaktionen: tollertyp
@SaschaHa Schau noch mal in #6, es besteht kein Zusammenhang, die Schleife soll immer von 1 bis 20 (inkl.) laufen (also 20-mal etwas ausgeben) und pieces kann sich ändern, ist aber nicht kleiner 2.

inter soll für Intervals stehen ... aber ohne Kontext ist auch das nicht verständlich.
 
CyborgBeta schrieb:
inter soll für Intervals stehen ... aber ohne Kontext ist auch das nicht verständlich.
Dann sind die 0.05 also doch als 1/20 gemeint, sodass das Intervall eben bei 1.0 endet?
Ansonsten wirf mal einen Blick auf meinen vorherigen Beitrag.
 
  • Gefällt mir
Reaktionen: CyborgBeta

Ähnliche Themen

Zurück
Oben