www.vorhilfe.de
- Förderverein -
Der Förderverein.

Gemeinnütziger Verein zur Finanzierung des Projekts Vorhilfe.de.
Hallo Gast!einloggen | registrieren ]
Startseite · Mitglieder · Impressum
Forenbaum
^ Forenbaum
Status VH e.V.
  Status Vereinsforum

Gezeigt werden alle Foren bis zur Tiefe 2

Navigation
 Startseite...
 Suchen
 Impressum
Das Projekt
Server und Internetanbindung werden durch Spenden finanziert.
Organisiert wird das Projekt von unserem Koordinatorenteam.
Hunderte Mitglieder helfen ehrenamtlich in unseren moderierten Foren.
Anbieter der Seite ist der gemeinnützige Verein "Vorhilfe.de e.V.".
Partnerseiten
Weitere Fächer:

Open Source FunktionenplotterFunkyPlot: Kostenloser und quelloffener Funktionenplotter für Linux und andere Betriebssysteme
Forum "Schul-Informatik Algorithmen" - java ungenauigkeit
java ungenauigkeit < Algorithmen < Schule < Informatik < Vorhilfe
Ansicht: [ geschachtelt ] | ^ Forum "Schul-Informatik Algorithmen"  | ^^ Alle Foren  | ^ Forenbaum  | Materialien

java ungenauigkeit: Frage (beantwortet)
Status: (Frage) beantwortet Status 
Datum: 20:38 So 22.10.2006
Autor: Bit2_Gosu

Hallo !

Ich war kurz vorm austicken als ich festgestellt hab, warum mein programm nicht funktioniert...

Um zu zeigen, voran es lag, hab ich das problem mal vereinfacht rausgegriffen:

1: public class tester1 {
2:
3: private double right;
4: private double left;
5:
6: public tester1 () {
7: }
8:
9: public void testen () {
10:
11: left = -0.1;
12: right = -0.08;
13:
14: while (right < 0.1) {
15:
16: right = left+0.02;
17:
18: System.out.println("left:" + left + "  " + "right:" + right);
19:
20: left = left + 0.02;
21: }
22: }
23: }


es wird bei mir ausgegeben:

left:-0.1  right:-0.08  
left:-0.08  right:-0.06  
left:-0.06  right:-0.039999999999999994  
left:-0.039999999999999994  right:-0.019999999999999993  
left:-0.019999999999999993  right:6.938893903907228E-18  
left:6.938893903907228E-18  right:0.020000000000000007  
left:0.020000000000000007  right:0.04000000000000001  
left:0.04000000000000001  right:0.06000000000000001  
left:0.06000000000000001  right:0.08000000000000002  
left:0.08000000000000002  right:0.10000000000000002

das darf doch wohl nicht wahr sein !!!!!!!!
warum verfälschen sich die werte auf einmal. eigentlich sollte

left:-0.1  right:-0.08  
left:-0.08  right:-0.06  
left:-0.06  right:-0.04  
left:-0.04  right:-0.02  
left:-0.02  right:0

usw. ausgegeben werden...

Bitte helft mir und erklärt mir, woher dieser irsinn kommt und was ich dagegen machen kann.

        
Bezug
java ungenauigkeit: Antwort
Status: (Antwort) fertig Status 
Datum: 21:59 So 22.10.2006
Autor: piet.t

Hallo Richard,

das Problem dabei ist, dass die Gleitkommavariablen intern ja binär dargestellt werden - und 0,02 in Binärdarstellung ist leider ein unendlicher "Binärbruch" ("Dezimalbruch" passt hier ja nicht....).

Etwas genauer: in Bnärdarstellung ist 0,02: 0,000001010001111.... und irgendwann wird's periodisch. Der Computer nimmt zwar ein paar mehr Nachkommastellen als ich, aber nichtsdestotrotz muss er irgendwann einmal abbrechen und dann entstehen Rundungsfehler. Nimmt man meine Beispieldarstellung und wandelt sie wieder in eine Dezimalzahl um, dann kommt eben nur noch 0,019989013671875 raus.

Wie kann man das vermeiden?
1. Möglichkeit: die Ergebnisse zwischendurch immer mal wieder auf eine vernünftige Genauigkeit runden, wobei ich nicht weiss, ob java da was vernünfitges anzubieten hat....
2. Möglichkeit: die Klasse BigInteger im Paket java.math stellt eine Dezimalzahl beliebiger Genauigkeit dar, d.h. da verschwinden dann auch die Rundungsfehler aus der Umwandlung ins Binärformat. Allerdings wird das Handling dann etwas umständlicher und das Programm wird schätzungsweise auch um ein paar Größenordnungen langsamer (was in diesem Beispiel aber noch nicht wirklich spürbar ist). Hier mal mein Beispiel:
1: public class Tester {
2:
3:
4: public Tester() {
5: }
6:
7: public static void main(String[] args) {
8: BigDecimal right;
9: BigDecimal left;
10: final BigDecimal step = new BigDecimal("0.02");
11: final BigDecimal limit = new BigDecimal("0.1");
12:
13: left = new BigDecimal("-0.1");
14: right = new BigDecimal("-0.08");
15:
16: while (right.compareTo(limit)< 0) {
17:
18: right = left.add(step);
19:
20: System.out.println("left:" + left + "  " + "right:" + right);
21:
22: left = left.add(step);
23: }
24: }
25: }


Damit sieht die Ausgabe wohl so aus, wie Du das erwartest. Wenn Du zu dem Beispiel noch Fragen hast, dann melde Dich einfach nochmal.

Gruß

piet

Bezug
                
Bezug
java ungenauigkeit: Frage (beantwortet)
Status: (Frage) beantwortet Status 
Datum: 23:40 So 22.10.2006
Autor: Bit2_Gosu

Hallo Piet !

Vielen Dank für deine ausführliche Antwort !

Aber leider wird bei mir wenn ich dein programm nehme immer "cannot find symbol -class BigDecimal" angezeigt.
ich hab erst vor 3 Tagen mit java angefangen, deshalb bin ich mir nicht so sicher, aber ganz oben muss doch   "import java.lang.Math" hin, oder?? trotzdem klappts aber leider nicht ;)

am tollsten wäre es für mich natürlich wenn du mir zeigen könntest wie ich BigDecimal in meinem Programm integrieren kann ;)

Gruss Richard

Bezug
                        
Bezug
java ungenauigkeit: Antwort
Status: (Antwort) fertig Status 
Datum: 13:29 Mo 23.10.2006
Autor: Martin243

Hallo,

das Problem ist nur der Ort, an dem man diese Klasse findet. Die richtige Importanweisug muss lauten:

import java.math.BigDecimal;

Dann sollte alles wieder funktionieren.

Unter []Java-API kannst du im linken unteren Frame jede Klasse finden und in der Beschreibung dazu auch, wo du sie findest.


Gruß
Martin

Bezug
                        
Bezug
java ungenauigkeit: Mitteilung
Status: (Mitteilung) Reaktion unnötig Status 
Datum: 18:03 Mo 23.10.2006
Autor: piet.t

Hoppla, das import java.math.BigDecimal; habe ich beim Kopieren doch glatt verpasst....Sorry! Aber Martin hat das ja schon geklärt!

Gruß

piet

Bezug
                                
Bezug
java ungenauigkeit: Frage (beantwortet)
Status: (Frage) beantwortet Status 
Datum: 21:13 Mo 23.10.2006
Autor: Bit2_Gosu

Ok super ich danke euch beiden !

Grad noch eine letzte schnelle Frage, da ich mich für die rundmethode entschieden hab ;)

kennt jemand einen befehl, mit dem man die anzahl an nachkommastellen eines doubles rausfinden kann?
und wenn ja, wie findet man solche befehle ?



Bezug
                                        
Bezug
java ungenauigkeit: Antwort
Status: (Antwort) fertig Status 
Datum: 19:37 Mi 25.10.2006
Autor: piet.t

Hallo,
>  
> kennt jemand einen befehl, mit dem man die anzahl an
> nachkommastellen eines doubles rausfinden kann?

Auf Anhieb wüsste ich da jetzt nichts, es kommt dann ja auch wieder darauf an, ob man Dezimal- oder Binärdarstellung meint, ob Nullen an letzter Stelle mitgezählt werden sollen (die haben ja immerhin auch Aussagekraft),.... Ausserdem reden wir hier ja von Gleitpunktzahlen und wie viele Nachkommastellen hat [mm] 1,375*10^{-20}??? [/mm]

Ich denke Du willst ja eigentlich auf eine feste Zahl von Dezimalstellen runden - da wäre []hier ein Beispiel, wie man sowas in java anfangen kann.

> und wenn ja, wie findet man solche befehle ?
>  

Befehle gibt es in java ja nicht allzu viele (es gibt meines Wissens weniger als 20 reservierte Schlüsselworte in der eigentlichen Programmiersprache), aber eine riesige Klassenbibliothek, die Methoden für alles mögliche bereitstellt (System.out.println() ist ja auch kein Befehl sondern eine Methode einer java-Standardklasse).

Bleibt die Frage, wie findet man die passende Mehtode zum Problem. Und da ist mein Weg üblicherweise langes, mehr oder weniger systematisches Stöbern in der
[]API-Dokumentation der java-Standardklassen.
In unserem Beispiel könnte man foglendermaßen überlegen: Runden hat möglicherweise was mit Mathe zu tun, also wären Kandidaten das Paket java.math oder die Klasse java.lang.Math (man beachte den Unterschied). Ausserdem könnte es noch etwas mit den Datentypen float oder double zu tun haben - hier empfiehlt sich dann ein Blick auf die entsprechenden Wrapper-Klassen  (die heißen so, weil sie den elementaren Datentyp "einwickeln") java.lang.Float oder java.lang.Double.
Das ist am Anfang fürchterlich mühsam, aber mit der Zeit kriegt man einen Überblick über die wichtigsten Klassen und Pakete und gewint ein Gefühl dafür, wo man mit der Suche Anfangen könnte.

Gruß

piet

Bezug
                                                
Bezug
java ungenauigkeit: Mitteilung
Status: (Mitteilung) Reaktion unnötig Status 
Datum: 23:23 So 29.10.2006
Autor: Bit2_Gosu

vielen dank Piet !!!

Habs jetzt mal so gelöst:

1: private int getNachkommastellen(final double x) {
2:
3: if (x==Math.round(x)) { 
4: return(0);   
5: }
6:
7: else {    
8: return((""+x).length()-(""+((int)x)).length()-1);   
9: }
10: }


Bezug
Ansicht: [ geschachtelt ] | ^ Forum "Schul-Informatik Algorithmen"  | ^^ Alle Foren  | ^ Forenbaum  | Materialien


^ Seitenanfang ^
ev.vorhilfe.de
[ Startseite | Mitglieder | Impressum ]