Satz des Pythagoras und Rundungsprogramm


Snaer

Grünschnabel
Guten Tag,

Ich muss ein Programm schreiben, das bestimmt ob ein Dreieck rechtwinklig ist, indem es 3 double Werte bekommt und ein boolean Wert ausgibt und zudem noch eine double Zahl einliest und diese auf eine bestimmte Nachkommastelle rundet die man als einen Integer Wert festlegen kann.
Dabei stellen sich mir aktuell die Probleme, dass mein Programm anscheinend die Werte beim Satz des Pythagoras nicht korrekt rundet, so sagt es mir zum Beispiel das 7^2+2^2 != 7.28^2 sei, obwohl dies ein rechtwinkliges Dreieck sein müsste.
Und zum anderen soll das Programm in der zweiten Methode falls der eingegebene Integer Wert kleiner als 0 oder größer als 10 ist den double Wert unverändert wieder ausgeben
Mein Code sieht bislang so aus:
Java:
import java.util.Scanner;

public class Functionality {

    public static void main(String[] args) {
        Scanner s = new Scanner(System.in);
        double kathete1;
        double kathete2;
        double hypothenuse;
        System.out.println("Bitte geben Sie die Länge der ersten Kathete ein");
        kathete1= s.nextDouble();
        System.out.println("Bitte geben Sie die Länge der zweiten Kathete ein");
        kathete2 = s.nextDouble();
        System.out.println("Bitte geben Sie die Länge der Hypothenuse ein");
        hypothenuse = s.nextDouble();
        boolean result  = istRechtwinkligesDreieck  (kathete1, kathete2,hypothenuse);
        s.close();
    }
    public static boolean istRechtwinkligesDreieck (double kathete1, double kathete2, double hypothenuse) {
        double result = kathete1 * kathete1 + kathete2 * kathete2;
        int i;
        i = (int) result;
        if(i == hypothenuse * hypothenuse) {
            System.out.println("Das Dreieck ist rechtwinklig");
            return true;
            }
        else {
            System.out.println("Das Dreieck ist nicht rechtwinklig");
            return false;
        }
    }
    public static double abschneiden () {
        Scanner scan = new Scanner(System.in);
        System.out.println("Bitte geben Sie eine Dezimalzahl ein");
        double value = scan.nextDouble();
        System.out.println("Bitte geben Sie die gewünschte Nachkommastelle ein");
        int kommastelle = scan.nextInt();
        scan.close();
        double result = Math.round(Math.pow(10, kommastelle) * value / Math.pow(10, kommastelle));
        System.out.println();
    }
    }
 
Zuletzt bearbeitet von einem Moderator:

Snaer

Grünschnabel
Das hatte ich eingefügt in der Hoffnung, dass mir das Programm den Wert dadurch abrunden würde. Leider klappt es nicht auch wenn ich result als einen double Wert lasse gibt mir das Programm lediglich aus das es sich um kein rechtwinkliges Dreieck handele.
 

Technipion

Erfahrenes Mitglied
Computer sind Maschinen mit endlichem Speicher. Deshalb können sie nur gerundete Werte speichern. Extra für diesen Zweck wurden schon vor langer Zeit Standards definiert, wie man Gleitkommaarithmetik vernünftig realisieren kann. Siehe z.B. hier: IEEE 754 – Wikipedia

so sagt es mir zum Beispiel das 7^2+2^2 != 7.28^2 sei, obwohl dies ein rechtwinkliges Dreieck sein müsste.
Nö. Multipliziere ich beide Seiten mit 100^2 ergibt sich 700^2 + 200^2 != 728^2. Und 530000 != 529984, also hat dein Computer alles richtig gemacht.

Grundsätzlich hast du bei Gleitkommawerten immer das Problem, dass sie sich eigentlich nicht richtig vergleichen lassen. Durch Rundungsfehler könnte ein 3.0 == 3.0 nach hinten losgehen. Programmierer vermeiden es daher floats genau zu vergleichen. Stattdessen wird eine Toleranz verwendet:
Statt float1 == float2 schreiben wir abs(float1 - float2) < toleranz. Dabei steht abs() für den Betrag (vom engl. absolute), und toleranz ist die gewünschte Genauigkeit. Z.B. prüft abs(a - b) < 0.000001 ob die Zahlen a und b um weniger als ein Millionstel voneinander abweichen.

Gruß Technipion
 

Snaer

Grünschnabel
Danke für die Antwort, den Teil mit dem Satz des Pythagoras funktioniert mittlerweile.
Allerdings fehlt mir noch immer der Teil das ich einen double Wert auf n Nachkommastellen abschneiden kann.
Leider fällt mir dazu keine passende Methode ein
 

Bratkartoffel

gebratene Kartoffel
Premium-User
Hi,

wenn du auf 2 Nachkommastellen willst, dann nimmst du deinen double und multiplizierst ihn mit 10^2. DAnn castest du das ganze auf einen long um und teilst es anschliessend wieder durch 10^2.

Ob dann bei einem System.out.println() dann auch wirklich 1.23 rauskommt, oder 1.2300000001 liegt dann an der IEEE Darstellung.

Übrigens: Hast du dir auch mal die Math.hypot(double, double) angeschaut?

Grüsse,
BK
 

Snaer

Grünschnabel
Wenn ich das so eingebe kommt bei mir aus irgendeinem Grund 1 :unsure:
Und gibt es auch eine allgemeine Lösung für n Nachkommastellen ?
Also ich möchte gerne einen Integer Wert eingeben der quasi festlegen soll wie viele Nachkommastellen ausgegeben werden
 

Bratkartoffel

gebratene Kartoffel
Premium-User
Hi,

bevor du deinen int durch 10^n teilst, musst du diesen natürlich erst wieder in einen double umwandeln.
Einfacher / schöner / "richtiger" wäre es aber, von Anfang an (und ausschliesslich) mit BigDecimal zu arbeiten.

Grüsse,
BK
 

Snaer

Grünschnabel
Hättest du eventuell ein Beispiel wie der Code damit aussehen könnte?
Ich bin leider noch ein blutiger Anfänger und kenne die Methode bisher garnicht :unsure:
 

Bratkartoffel

gebratene Kartoffel
Premium-User
Hi,

sollte in etwa so aussehen:
Java:
import java.math.BigDecimal;
import java.util.Scanner;

public class Functionality {
    public static void main(String[] args) {
        try (Scanner s = new Scanner(System.in)) {
            BigDecimal a, b, c;
            System.out.println("Bitte geben Sie die Länge der ersten Kathete ein");
            a = new BigDecimal(s.next());
            System.out.println("Bitte geben Sie die Länge der zweiten Kathete ein");
            b = new BigDecimal(s.next());
            System.out.println("Bitte geben Sie die Länge der Hypothenuse ein");
            c = new BigDecimal(s.next());

            boolean result = istRechtwinkligesDreieck(a, b, c);
            if (result) {
                System.out.println("Das Dreieck ist rechtwinklig");
            } else {
                System.out.println("Das Dreieck ist nicht rechtwinklig");
            }
        }
    }

    private static boolean istRechtwinkligesDreieck(BigDecimal a, BigDecimal b, BigDecimal c) {
        BigDecimal a2 = a.multiply(a);
        BigDecimal b2 = b.multiply(b);
        BigDecimal c2 = c.multiply(c);
        BigDecimal a2b2 = a2.add(b2);
        BigDecimal a2b2_rounded = abschneiden(a2b2, 2);
        BigDecimal c2_rounded = abschneiden(c2, 2);
        return a2b2_rounded.compareTo(c2_rounded) == 0;
    }

    private static BigDecimal abschneiden(BigDecimal value, int scale) {
        return value.setScale(scale, BigDecimal.ROUND_HALF_UP);
    }
}
Grüsse,
BK
 

Snaer

Grünschnabel
Danke für die Antwort, mittlerweile habe ich es hinbekommen indem ich den Wert zunächst mal 10 ^n genommen habe, anschließend zu einem Long gecastet und danach wieder zu einem double gecastet habe.
Danke für die Hilfe!