Durchschnittsberechner

Kenta1561

Bekanntes Mitglied
Hallo,

ich habe heute ein kleines Programm geschrieben womit man den Durschnitt von 10 Dezimalzahlen berechnen kann. Was das jetzt für ein Sinn hat, lege ich jetzt einfach mal beiseite.
Jedenfalls, hier erst mal mein Code:
Java:
package main;

import javax.swing.*;

/**
* Created by Kenta1561 on 2016/04/01.
*/
public class Main {

    public static void main(String[] args) {

        String[] numbers = new String[10];
        double sum, average, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10;

        for(int counter = 1; counter < 11; counter++) {

            numbers[counter-1] = JOptionPane.showInputDialog("Enter your " + counter + ". number.");

        }

        n1 = Double.parseDouble(numbers[0]);
        n2 = Double.parseDouble(numbers[1]);
        n3 = Double.parseDouble(numbers[2]);
        n4 = Double.parseDouble(numbers[3]);
        n5 = Double.parseDouble(numbers[4]);
        n6 = Double.parseDouble(numbers[5]);
        n7 = Double.parseDouble(numbers[6]);
        n8 = Double.parseDouble(numbers[7]);
        n9 = Double.parseDouble(numbers[8]);
        n10 = Double.parseDouble(numbers[9]);

        sum = n1+n2+n3+n4+n5+n6+n7+n8+n9+n10;
        average = sum/10;

        JOptionPane.showMessageDialog(null, "The average is " + average + ".");

    }
}

Wenn ich bei allen 10 Werten zum Beispiel 0,2532 (eingegeben habe ich natürlich 0.2532, nicht 0,2532) eingebe, sollte ja logischerweise als Ergebnis bzw. Durschnitt ja auch 0,2532 (bzw. 0.2532) rauskommen, jedoch lautet das Ergebnis: 0,25320000000000004. Was muss ich hier ändern, damit 0,2532 rauskommt und nicht 0,25320000000000004?

Nachtrag: Ich habe gerade mit System.out.println nachgeguckt wo der Fehler liegen könnte, ich habe festgestellt, dass das Umwandeln von String zu Double problemlos funktioniert, der Fehler müsste beim Berechnen von "sum" liegen.

MfG
Kenta1561
 
Zuletzt bearbeitet:

T_T

Bekanntes Mitglied
schon mit

Java:
DecimalFormat df = new DecimalFormat("#.##");
System.out.print(df.format(d));
probiert?
 

Jardcore

Top Contributor
Wirklich nicht einfach^^
Also Java macht da bisschen was nicht so sauber.
Die JVM speichert die double Werte nicht so wie man eigentlich denkt.
Um dein Problem zu vermeiden benötigst du BigDecimal und beschränkst deine Berechnungen auf den 64Bit Raum. Ich glaube die JVM speichert die double nur bis 64Bit und danach werden sie interpretiert. Genauer kann man das hier nachlesen (english): http://www.drdobbs.com/jvm/javas-floating-point-imprecision/240168744

Ich habe deinen Code mal ein wenig angepasst.
Java:
public class Main {

    public static void main(String[] args) {

        int maxNumbers = 10;
        BigDecimal sum = new BigDecimal(0, MathContext.DECIMAL64);
        BigDecimal avg = new BigDecimal(0, MathContext.DECIMAL64);

        for(int counter = 0; counter < maxNumbers; counter++) {
            String eingabe = JOptionPane.showInputDialog(String.format("Enter your %d number.", counter + 1));
            sum = sum.add(new BigDecimal(Double.parseDouble(eingabe), MathContext.DECIMAL64));
        }
     
        avg = sum.divide(new BigDecimal(maxNumbers, MathContext.DECIMAL64));

        JOptionPane.showMessageDialog(null, String.format("The average is %f.", avg));
    }
}

Das ist jetzt natürlich ein riesen Aufwand, den du eigentlich nicht brauchst, denn wenn du rundest wird sowieso der richtige Wert ausgegeben.

Also reicht es auch wenn du einfach nur eine formatierte Ausgabe benutzt.
Java:
public class Main {

    public static void main(String[] args) {

        double sum = 0;
        int maxNumbers = 10;

        for(int counter = 0; counter < maxNumbers; counter++) {
            String eingabe = JOptionPane.showInputDialog(String.format("Enter your %d number.", counter + 1));
            sum += Double.parseDouble(eingabe);
        }

        JOptionPane.showMessageDialog(null, String.format("The average is %f.", sum / maxNumbers));
    }
}

Edit: Noch zur formatierten Ausgabe, das ist dieser Teil mit String.format("",args);
Hinten wie du bestimmt bemerkt hast kommt der Wert hinnein.
Und vorne kommt der String in dem der Wert ausgeben werden soll.
dabei steht:
%d für ein Integer, ganzzahlen Wert
%f für einen Fließkommawert
%s für Strings
%c für Character (glaube ich^^)

Wenn du nur die letzten zwei Nachkommastellen des Fließkommawertes ausgeben willst kannst du zum Beispiel %.2f schreiben.
 

Joose

Top Contributor
Ich glaube die JVM speichert die double nur bis 64Bit und danach werden sie interpretiert.
Genau, für double werden 8 bytes (64bit) verwendet. Ansonsten passiert hier das gleiche wie bei anderen Datentypen -> Überlauf
Wenn man größere Zahlen braucht, muss man einen anderen Datentyp ala BigInteger/BigDecimal verwenden.

Das Problem ist das nicht alle Dezimalzahlen genau dargestellt werden können (je nachdem welche Basis man verwendet).
Kurzes Beispiel: 1/3 = 0,333 (periodisch)
In Dezimalsystem kann diese Zahl als Fließkomma nicht genau dargestellt werden, im Dualsystem hingegen ist es möglich. Dafür können aber andere Fließkommazahlen ohne Problem im Dezimalsystem aber nicht im Dualsystem dargestellt werden.
https://www.google.at/search?q=floa...1n-VoGuD8TsaN-zkZgD#q=floating+number+problem

Das ist auch ein Grund warum man zum Beispiel immer in Cent rechnen sollte wenn man mit Geldbeträgen rechnet ;) eine kleine ungenauigkeit könnte große Auswirkungen haben und teuer kommen.
 

stg

Top Contributor
@Joose
Bei mir ist 1/3 im Dualsystem immer noch periodisch. 1/3 _10 = 0.(01)... _2
Sieht man leicht, wenn man 1/3 als geometrische Reihe schreibt:
1/3 = 1/(1-1/4)-1 = \sum_{i=1..\inf} 1/2^{2i}

Oder meinst du was anderes? :)
 
Zuletzt bearbeitet:

AndiE

Top Contributor
An sich ist das ja Eulen nach Athen tragen: 1/10=409,6/4096= 6553,6/65536. Es bleibt also ((fast) immer ein Restbetrag übrig, der verschwindend gering sein kann. Das ergibt dann diese Umwandlungs- und Anzeigefehler.
 

Neue Themen


Oben