PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [Java] Problem mit toString-Darstellung


Sergej
2010-01-09, 12:06:06
Hi,

ich muss Intervalle etc. programmieren (Kontext hier nicht so wichtig). Die Erstllung des Konstruktors habe ich mittlerweile hinbekommen. Nun soll das Intervall per toString in der Form [a, b] ausgegeben werden. Daran scheitere ich leider zurzeit.

Derzeitige Ausgabe ist:

[I@3e25a5
[I@19821f
[1, 2]
[3, 4]


Hier der Code:

public class Interval {

public static void main(String[] args) {

Interval eins = new Interval (1, 2);
Interval zwei = new Interval (3, 4);

System.out.println(eins.x.toString());
System.out.println(zwei.x.toString());

System.out.println("[" + eins.x[0] + ", " + eins.x[1] + "]");
System.out.println("[" + zwei.x[0] + ", " + zwei.x[1] + "]");

}

int[] x = new int[2]; // Erstellung des Arrays der Länge 2

/**
* Konstruktor zur Generierung eines Intervalls als Array
* @param a
* @param b
*/
public Interval(int a, int b) {

x[0] = a;
x[1] = b;

}

/**
* Darstellung des Intervall-Arrays als [a, b]
*/
public String toString() {

return "[" + x[0] + ", " + x[1] + "]";

}

/* boolean isEmpty() {

}

float length() {

}

float getLeftEndpoint() {

}

float getRightEndpoint() {

}

Interval add(Interval i) {

}

Interval mult(Interval i) {

} */

}

Monger
2010-01-09, 12:21:17
Siehe hier:


System.out.println(eins.x.toString());
System.out.println(zwei.x.toString());


Warum rufst du denn hier die "toString" Methode von x auf? x ist ein Array, und du kannst zwar auf jedem Objekt toString aufrufen, da kommt aber nicht immer was sinnvolles raus.

Lass einfach das x weg:


System.out.println(eins.toString());
System.out.println(zwei.toString());

So rufst du nämlich auch tatsächlich die toString Methode auf, die du selbst überschrieben hast.


Edit: der Tippfehler wäre dir gar nicht erst unterlaufen, wenn du nicht dieses kryptische Array als Speicher benutzen würdest, sondern ausdrucksstarke Variablen. Wenn dein Objekt tatsächlich ein Intervall darstellt, wären doch zwei Attribute namens "lowerBound" und "upperBound" plausibel. Mehr als eine Ober- und Untergrenze hat ein Intervall nunmal nicht. Das macht den restlichen Code dann auch gleich viel lesbarer.

Sergej
2010-01-09, 12:23:52
Siehe hier:


System.out.println(eins.x.toString());
System.out.println(zwei.x.toString());


Warum rufst du denn hier die "toString" Methode von x auf? x ist ein Array, und du kannst zwar auf jedem Objekt toString aufrufen, da kommt aber nicht immer was sinnvolles raus.

Lass einfach das x weg:


System.out.println(eins.toString());
System.out.println(zwei.toString());

So rufst du nämlich auch tatsächlich die toString Methode auf, die du selbst überschrieben hast.
Argh, das war naheliegend. Danke für die Hilfe!

Monger
2010-01-09, 12:28:32
Noch ein Nachtrag: das wäre dir ebenfalls nicht passiert, wenn du x als private gekennzeichnet hättest. ;)

Pinoccio
2010-01-09, 12:51:08
Das Problem ist ja nun gelöst, aber ein paar Anmerkungen:
- Wie Monger schon sagt: einfach zwei Variablen sind da sinnvoller, diese ggfs. auf private setzen + get/set...()
- Plausibilitätsprüfung beim setzen: lowerBound =< upperBound
- imho lieber double als float
- nicht getRight/LeftEndpoint() sonder getLower/UpperBound()
- was ist mit unbound, left/right open/closed
- und schön an ISO 31-11 (http://en.wikipedia.org/wiki/ISO_31-11) denken ;-)
- equals() und evtl. clone() ebenfalls überschreiben

mfg

PatkIllA
2010-01-09, 13:48:12
Und bei Zahlenausabe (und auch Eingabe) immer an Internationalisierung denken. Es kommt tatsächlich vor, dass Leute dann per Stringoperationen Kommas und Punkte verarbeiten.

Sergej
2010-01-09, 13:52:22
Das Problem ist ja nun gelöst, aber ein paar Anmerkungen:
- Wie Monger schon sagt: einfach zwei Variablen sind da sinnvoller, diese ggfs. auf private setzen + get/set...()
- Plausibilitätsprüfung beim setzen: lowerBound =< upperBound
- imho lieber double als float
- nicht getRight/LeftEndpoint() sonder getLower/UpperBound()
- was ist mit unbound, left/right open/closed
- und schön an ISO 31-11 (http://en.wikipedia.org/wiki/ISO_31-11) denken ;-)
- equals() und evtl. clone() ebenfalls überschreiben

mfg
Also, die Methodennamen sind vorgegeben. Um die anderen Anmerkungen kümmere ich mich später.

Ich habe jetzt das Array entfernt und dafür Variablen benutzt. Eclipse markiert mir den Aufruf der Methoden isEmpty und length mit dem Hinweis:

Multiple markers at this line
- The method isEmpty(float) in the type Interval is not applicable for the arguments
(Interval)
- Line breakpoint:Interval [line: 11] - main(String[])

und

The method length(float) in the type Interval is not applicable for the arguments (Interval)


public class Interval {

public static void main(String[] args) {

Interval x = new Interval (1, 2);
Interval y = new Interval (3, 4);

System.out.println(x.toString());
System.out.println(y.toString());

System.out.println("isEmpty? " + isEmpty(x));
System.out.println("length: " + length(x));
//System.out.println(x.add(y));

}

float lowerBound, upperBound;

public Interval(float a, float b) {

lowerBound = a;
upperBound = b;

}

public String toString() {

return "[" + lowerBound + ", " + upperBound + "]";

}

boolean isEmpty(float a) {

return lowerBound > upperBound;

}

float length(float a) {

return upperBound - lowerBound;

}

...


EDIT: Ok, grad gemerkt, ich muss due Methoden so deklarieren:

boolean isEmpty(Interval a) {

Monger
2010-01-09, 13:58:53
Wieso haben "isEmpty" und "Length" überhaupt Übergabeparameter? :confused:

Du machst ja auch mit den übergebenen Parametern nichts.

RMC
2010-01-09, 13:59:28
System.out.println(x.toString());
System.out.println(y.toString());



Noch ein Hinweis:

Wenn du die "ToString()" Methode überschrieben hast, brauchst du die nicht aufrufen, das wird implizit gemacht.

Also ein

System.out.println(x);

reicht aus :)

Sergej
2010-01-09, 14:11:33
Wieso haben "isEmpty" und "Length" überhaupt Übergabeparameter? :confused:

Du machst ja auch mit den übergebenen Parametern nichts.
Wenn ich das so schreibe:

boolean isEmpty() {

return lowerBound > upperBound;

}

habe ich beim Aufruf den Fehler:

Multiple markers at this line
- Line breakpoint:Interval [line: 11] - main(String[])
- The method isEmpty() in the type Interval is not applicable for the arguments
(Interval)

Pinoccio
2010-01-09, 14:15:41
Also, die Methodennamen sind vorgegeben. Um die anderen Anmerkungen kümmere ich mich später.

Ich habe jetzt das Array entfernt und dafür Variablen benutzt. Eclipse markiert mir den Aufruf der Methoden isEmpty und length mit dem Hinweis:

Multiple markers at this line
- The method isEmpty(float) in the type Interval is not applicable for the arguments
(Interval)
- Line breakpoint:Interval [line: 11] - main(String[])

und

The method length(float) in the type Interval is not applicable for the arguments (Interval)
Du hats die main in einer Klasse zusammen mit dem Intervall, das verursacht diese Probleme zuständig!
Richtig so:
public class Interval {
public static void main(String[] args) {

Interval x = new Interval (1, 2);
Interval y = new Interval (3, 4);

System.out.println(x.toString());
System.out.println(y.toString());

System.out.println("isEmpty? " + x.isEmpty()); // bezieht sich auf x!
System.out.println("length: " + x.length()); // hier ist die Länge von x gefragt!
}

boolean isEmpty() {
return lowerBound > upperBound;
}

float length() {
return upperBound - lowerBound;
}

EDIT: Ok, grad gemerkt, ich muss due Methoden so deklarieren:

boolean isEmpty(Interval a) {Nene, siehe Quelltext. Du greifst auf die falschen Objekte zu.
Am besten du trennst die zu startende main von der Klasse Intervall.

mfg

Monger
2010-01-09, 14:16:35
Multiple markers at this line
- Line breakpoint:Interval [line: 11] - main(String[])
- The method isEmpty() in the type Interval is not applicable for the arguments
(Interval)


Ja, weil du in der Main halt bereits "isEmpty" mit entsprechendem Parameter aufrufst. Du musst natürlich auch da die Methodenaufrufe korrigieren.

Sergej
2010-01-09, 14:26:17
Danke, jetzt läufts.

Aber wo ist der Unterschied? Es lief, als ich die Methoden static deklariert habe, Parameter übergeben habe und ich den Methoden dann parameter.lowerBound bzw parameter.upperBound benutzt habe.

Und jetzt funktioniert es quasi, indem ich Methoden mit whatever.methode Aufrufe, dafür keine Parameter übergebe und die Methoden nicht static sind (heisst das dann dynamic? :)).

Code bis hierhin jetzt korrekt:

public class Interval {

public static void main(String[] args) {

Interval x = new Interval (1, 2);
Interval y = new Interval (10, 7);

System.out.println(x);
System.out.println(y);

System.out.println("isEmpty? " + x.isEmpty());
System.out.println("isEmpty? " + y.isEmpty());

System.out.println("length: " + x.length());
System.out.println("length: " + y.length());

System.out.println("getLeftEndpoint: " + x.getLeftEndpoint());
System.out.println("getRightEndpoint: " + y.getRightEndpoint());

System.out.println("getRightEndpoint: " + x.getRightEndpoint());
System.out.println("getRightEndpoint: " + y.getRightEndpoint());

//System.out.println(x.add(y));

}

float lowerBound, upperBound;

public Interval(float a, float b) {

lowerBound = a;
upperBound = b;

}

public String toString() {

return "[" + lowerBound + ", " + upperBound + "]";

}

boolean isEmpty() {

return lowerBound > upperBound;

}

float length() {

return upperBound - lowerBound;

}

float getLeftEndpoint() {

return lowerBound;

}

float getRightEndpoint() {

return upperBound;

}

...

PatkIllA
2010-01-09, 14:30:01
das andere wäre dann objektorientiert. ;)
Statische Methoden kannst du auch ohne ein instanziertes Objekt (Parameter nicht mitgerechnet) auf der Klasse aufrufen. Das sollte aber eigentlich vorher schon in der Übung vorgekommen sein.

Pinoccio
2010-01-09, 14:32:23
Danke, jetzt läufts.

Aber wo ist der Unterschied? Es lief, als ich die Methoden static deklariert habe, Parameter übergeben habe und ich den Methoden dann parameter.lowerBound bzw parameter.upperBound benutzt habe.

Und jetzt funktioniert es quasi, indem ich Methoden mit whatever.methode Aufrufe, dafür keine Parameter übergebe und die Methoden nicht static sind (heisst das dann dynamic? :)).
Das Gegenteil zu static ist non-static, sagt zumindestd er Compiler z. B. beid er Fehlermeldung: Cannot access non-static property in static context.
Hier ists quasi andersrum, du hats die static main und greifst auf verschieden Objekte vom Typ Intervall zu. Ich erneuer hier nochmal meinen Rat, die main und die eigentliche Klasse zu trennen!

Code bis hierhin jetzt korrekt:
System.out.println("getLeftEndpoint: " + x.getLeftEndpoint());
System.out.println("getRightEndpoint: " + y.getRightEndpoint()); // <- should be left!

System.out.println("getRightEndpoint: " + x.getRightEndpoint());
System.out.println("getRightEndpoint: " + y.getRightEndpoint());



class IntervallTester {

public static void main(String[] args) {

Interval x = new Interval (1, 2);
Interval y = new Interval (10, 7);

System.out.println(x.toString());
System.out.println(y.toString());
// usw.

}
}
Ich würde toString() nutzen, einfach, weil es klarer ist, println (http://java.sun.com/j2se/1.4.2/docs/api/java/io/PrintStream.html#method_summary) nimmt ja nicht nur Strings. Der Compiler macht eh aus beiden Varianten das selbe.

class Intervall {

private float lowerBound;
private float upperBound;

Intervall(float lower, float upper) {

this.lowerBound = lower;
this.upperBound = upper;
}

boolean isEmpty() {

return this.lowerBound > this.upperBound;
}

// usw.
}

mfg

Sergej
2010-01-09, 14:44:43
Ich erneuer hier nochmal meinen Rat, die main und die eigentliche Klasse zu trennen!

Ich kann Dir hier leider nicht folgen. Meinst du den Aufruf (s.u.) aus der Main rausnehmen? Wie soll ich das dann mit den Werten aufrufen?

Interval x = new Interval (1, 2);
Interval y = new Interval (10, 7);


Eine Frage hätte ich noch zum addieren:

System.out.println(x.add(y));

für

Interval add(Interval i) {

lowerBound = lowerBound + i.lowerBound;
upperBound = upperBound + i.upperBound;

}
.
Sehe ich das also richtig, dass ich hier dynamisch die Methode add aufrufe mit dem Intervall x, und ihm dann zum addieren als Parameter das Intervall y gebe?

Hier gibt es jetzt lt. Eclipse noch den Fehler
This method must return a result of type Interval.
Wie muss ich die Methode zusammenschustern, dass es wieder ein Type Interval wird? In Interval selbst ist doch auch nur lowerBound und upperBound definiert, nichts anderes mache ich doch in der add-Methode?!

PatkIllA
2010-01-09, 14:49:28
return new Interval(lowerBound + i.lowerBound, upperBound + i.upperBound);
(Auch wenn das mathematisch falsch ist)

Dabei bleibt das ursprüngliche Interval unverändert und es entsteht ein neues Objekt.

Du solltest dich erstmal mit Objektorientierung vertraut machen, bevor du jetzt weiter im Nebel stocherst.

Sergej
2010-01-09, 14:54:16
class IntervallTester {

public static void main(String[] args) {

Interval x = new Interval (1, 2);
Interval y = new Interval (10, 7);

System.out.println(x.toString());
System.out.println(y.toString());
// usw.

}
}[/code]
In der Aufgabe steht: "Schreiben Sie eine Methode main zum Testen der Klasse Interval. Vergessen Sie nicht, Ihre
Klasse zu kommentieren.". Das interpretiere ich so, dass ich das ganze in der Klasse Interval testen soll.

PatkIllA
2010-01-09, 14:57:08
Du hast doch auch eine main Methode, die die Klasse Interval testet.

Sowas macht man eigentlich nur wenn man mal schnell was zum Ausprobieren runterhacken will.
Werden die Aufgaben bei euch automatisch verifiziert? Dann bist du evtl. mit der statischen Methode in der Klasse selbst auf der besseren Seite.

Pinoccio
2010-01-09, 15:01:44
Ich kann Dir hier leider nicht folgen. Meinst du den Aufruf (s.u.) aus der Main rausnehmen? Wie soll ich das dann mit den Werten aufrufen?siehe mein edit, beides in einem Ordner aber zwei Dateien abspeichern, beides compilieren und den IntervallTester starten.
In der Aufgabe steht: "Schreiben Sie eine Methode main zum Testen der Klasse Interval. Vergessen Sie nicht, Ihre
Klasse zu kommentieren.". Das interpretiere ich so, dass ich das ganze in der Klasse Interval testen soll.Meine Variante mit getrennten Klassen deckt die Aufgabenstellung m. M. n. auch ab und ist - wie du ja merkst - besser. ;-)

Eine Frage hätte ich noch zum addieren:

System.out.println(x.add(y));

für

Interval add(Interval i) {

lowerBound = lowerBound + i.lowerBound;
upperBound = upperBound + i.upperBound;

}
.
Sehe ich das also richtig, dass ich hier dynamisch die Methode add aufrufe mit dem Intervall x, und ihm dann zum addieren als Parameter das Intervall y gebe?

Hier gibt es jetzt lt. Eclipse noch den Fehler
This method must return a result of type Interval.
Wie muss ich die Methode zusammenschustern, dass es wieder ein Type Interval wird? In Interval selbst ist doch auch nur lowerBound und upperBound definiert, nichts anderes mache ich doch in der add-Methode?!Dazu solltest du dir klar machen, was add eigentlich machen soll, ich finde das nicht offensichtlich. Deine derzeitige Variante verschiebt das Intervall. D. h. mit I1=[a, b] und I2=[c, d] wird I1.add(I2) auf [a+c, b+d] verschoben. Ich sehe da keine Addition drin. Soviel zum "mathematischen". (sign@PatkIllA)

Nun zum Programmieren:
Variante a), wäre mein Favorit, ist aber Geschmackssache:
static Intervall add(Interval i1, Intervall i2) {
Interval result=new Intervall(i1.lowerBound + i2.lowerBound, i1.upperBound + i2.upperBound);
return result;
}
Variante b), Finde ich persönlich unschön, weil das Ergebnis quasi zweimal zurückkommt. (Auch wenn SUN sowas an mnchen Stellen macht.)
Intervall add(Interval i1, Intervall i2) {
i1.setBounds(i1.lowerBound + i2.lowerBound, i1.upperBound + i2.upperBound);
return i1;
}
Variante c), imho die intuitivste Variante, da sie die imAlltag übliche Infix-Notation ein wenig nachbildet.
void add(Intervall i2) {
this.setBounds(this.lowerBound + i2.lowerBound, this.upperBound + i2.upperBound);
}

Sauberer noch wäre es, die zugriffe auf lower/upperBounds über getter zu leiten.

mfg

Sergej
2010-01-09, 15:26:20
Zum Mathematischen:

In der Aufgabenstellung ist dieser Artikel als Grundlage genannt: http://de.wikipedia.org/wiki/Intervallarithmetik

Und dort ist Addition als [x1,x2] + [y1,y2] = [x1 + y1,x2 + y2] beschrieben.

Pinoccio
2010-01-09, 15:33:58
Zum Mathematischen:

In der Aufgabenstellung ist dieser Artikel als Grundlage genannt: http://de.wikipedia.org/wiki/Intervallarithmetik

Und dort ist Addition als [x1,x2] + [y1,y2] = [x1 + y1,x2 + y2] beschrieben.Ah, okay. So kann man es rechnen (und wenn man so denkt, ist die Addition dann auch natürlich so definiert.)
Hi9nweis: Du musst mit plus/minus unendlich aufpassen!

Ich hatte eher Mengenlehre im Hinterkopf, wo ich die Addition als Vereinigung (http://de.wikipedia.org/wiki/Mengenlehre#Vereinigungsmenge) zwei Intervalle gedacht hätte, aber da wäre auch nicht gut gegangen bzw. beliebig kompliziert.

mfg

Sergej
2010-01-09, 16:11:59
So, eine letzte Frage noch:

Ich habe jetzt doch die Aufrufe in eine Testklasse gepackt:


public class IntervalTest {

public static void main(String[] args) {

Interval x = new Interval (14, 19);
Interval y = new Interval (8, 15);

System.out.println(x.toString());
System.out.println(y.toString());

System.out.println("isEmpty? " + x.isEmpty());
System.out.println("isEmpty? " + y.isEmpty());

System.out.println("length: " + x.length());
System.out.println("length: " + y.length());

System.out.println("getLeftEndpoint: " + x.getLeftEndpoint());
System.out.println("getLeftEndpoint: " + y.getLeftEndpoint());

System.out.println("getRightEndpoint: " + x.getRightEndpoint());
System.out.println("getRightEndpoint: " + y.getRightEndpoint());

System.out.println("add: " + x.add(y));

System.out.println("mult: " + x.add(y));

}

}



public class Interval {

float lowerBound, upperBound;

public Interval(float a, float b) {

lowerBound = a;
upperBound = b;

}

public String toString() {

return "[" + lowerBound + ", " + upperBound + "]";

}

boolean isEmpty() {

return lowerBound > upperBound;

}

float length() {

return upperBound - lowerBound;

}

float getLeftEndpoint() {

return lowerBound;

}

float getRightEndpoint() {

return upperBound;

}

Interval add(Interval i) {

float x1 = lowerBound;
float x2 = upperBound;
float y1 = i.lowerBound;
float y2 = i.upperBound;

return new Interval(x1 + y1, x2 + y2);

}

Interval mult(Interval i) {

float x1 = lowerBound;
float x2 = upperBound;
float y1 = i.lowerBound;
float y2 = i.upperBound;

return new Interval(
(Math.min( Math.min( (x1 * y1) , (x1 * y2) ) , Math.min( (x2 * y1) , (x2 * y2) ))),
(Math.min( Math.min( (x1 * y1) , (x1 * y2) ) , Math.min( (x2 * y1) , (x2 * y2) )))
);

}

}


Wieso erhalte ich beim Ergebnis der Mult. immer das gleiche, wie bei der Add.?

[14.0, 19.0]
[8.0, 15.0]
isEmpty? false
isEmpty? false
length: 5.0
length: 7.0
getLeftEndpoint: 14.0
getLeftEndpoint: 8.0
getRightEndpoint: 19.0
getRightEndpoint: 15.0
add: [22.0, 34.0]
mult: [22.0, 34.0]

Pinoccio
2010-01-09, 16:15:24
So, eine letzte Frage noch:

System.out.println("add: " + x.add(y));
System.out.println("mult: " + x.add(y));


Wieso erhalte ich beim Ergebnis der Mult. immer das gleiche, wie bei der Add.?
Weil du zweimal add aufrufst ;-)

mfg

Sergej
2010-01-09, 16:24:38
Weil du zweimal add aufrufst ;-)

mfg
AAAAARGH :D Danke.

Sergej
2010-01-11, 19:14:47
Ich will diesen Thread noch mal für eine weitere Frage missbrauchen.

Ich habe folgenden Code:

public class BigIntTest {

public static void main(String[] args) {

BigInt a = new BigInt("1234");

for(int i = 0; i < a.bigIntArray.length; i++) {

System.out.println(a.bigIntArray[i]);

}

}

}

und

public class BigInt {

byte[] bigIntArray;

public BigInt(String s) {

this.bigIntArray = s.getBytes();

}

}

Wieso bekomme ich als Ergebnis

49
50
51
52

bzw. was für eine Kodierung ist das? Ich möchte einfach ein Array vom Typ Byte, dass die Zahlen, die ich übergebe, auch GENAU SO in das Array schreibt. Falls es sich hier um ein Problem der Kodierung handelt, habe ich schon diese Seite gefunden: http://java.sun.com/javase/6/docs/technotes/guides/intl/encoding.doc.html. Anscheinend kann man als Parameter für getBytes() eine dieser Kodierungen einsetzen, aber das akzeptiert Eclipse nicht ...

patermatrix
2010-01-11, 19:39:28
Wieso bekomme ich als Ergebnis

49
50
51
52

Das sind die ASCII Werte (http://www.asciitable.com/) der Ziffern.

Sergej
2010-01-11, 19:48:56
Das sind die ASCII Werte (http://www.asciitable.com/) der Ziffern.
Ja, Danke. Und wie sag ich ihm, der soll nicht den Wert der ASCII-Zeichen, sondern einfach die Zahl einlesen?

robobimbo
2010-01-11, 20:04:46
einfach von jedem element 48 abziehen? :)

Pinoccio
2010-01-11, 20:18:41
einfach von jedem element 48 abziehen? :)Besser nicht. Auf anderen Rechnern muss das nicht funktionieren.

Besser ist: Integer.parseInt(String s) (http://java.sun.com/javase/6/docs/api/java/lang/Integer.html#parseInt%28java.lang.String%29) Parses the string argument as a signed decimal integer.

Ist es wieder Teil der Aufagbenstellung, das Rad neu zu erfinden? BigInteger (http://java.sun.com/javase/6/docs/api/java/math/BigInteger.html) gibt es doch schon. Und dutzende alternative BigNum-Bibliotheken.

mfg

Sergej
2010-01-11, 21:18:28
Ist es wieder Teil der Aufagbenstellung, das Rad neu zu erfinden?
Ja, leider.

Besser ist: Integer.parseInt(String s) (http://java.sun.com/javase/6/docs/api/java/lang/Integer.html#parseInt%28java.lang.String%29) Parses the string argument as a signed decimal integer.

BigInteger soll eine beliebige Länge haben. Wenn ich den String in ein int parse, habe ich ja wieder nur die max. Länge von int zur Verfügung.

Die Variante mit getBytes scheint doch eigtl recht vernünftig zu sein. Nur soll er halt keine Werte von ASCII Zeichen speichern ...

Pinoccio
2010-01-11, 21:25:38
Ja, leider.Darf ich fragen, in welchem Rahmen? (D. h. Abitur, Studium etc.)
Falls es umfangreicher werden soll (was ich anhand deiner Fragen eher nicht annehme): Vortrag (http://events.ccc.de/congress/2006/Fahrplan/events/1658.en.html) und Video (m4v) (http://mirror.fem-net.de/CCC/23C3/video/23C3-1658-en-bignum_arithmetic.m4v)BigInteger soll eine beliebige Länge haben. Wenn ich den String in ein int parse, habe ich ja wieder nur die max. Länge von int zur Verfügung.

Die Variante mit getBytes scheint doch eigtl recht vernünftig zu sein. Nur soll er halt keine Werte von ASCII Zeichen speichern ...Du sollst ja auch jeden Buchstaben einzeln als int parsen. ;-)
(Fürchterlich ineffektiv, aber es geht.)
String ziffern = "1234";
for (int i = 0 ; i<ziffern.length; i++) {
System.out.println("" + i "te Ziffer ist " + ziffern.charAt(i) );
}

mfg

Sergej
2010-01-11, 22:34:05
Darf ich fragen, in welchem Rahmen? (D. h. Abitur, Studium etc.)
Falls es umfangreicher werden soll (was ich anhand deiner Fragen eher nicht annehme): Vortrag (http://events.ccc.de/congress/2006/Fahrplan/events/1658.en.html) und Video (m4v) (http://mirror.fem-net.de/CCC/23C3/video/23C3-1658-en-bignum_arithmetic.m4v)Du sollst ja auch jeden Buchstaben einzeln als int parsen. ;-)
(Fürchterlich ineffektiv, aber es geht.)
String ziffern = "1234";
for (int i = 0 ; i<ziffern.length; i++) {
System.out.println("" + i "te Ziffer ist " + ziffern.charAt(i) );
}

mfg
Rahmen? Erstsemester Wirtschaftsinformatik.

Die for-Schleife kann doch aber auch nur so oft durchlaufen, bis die maximale Länge von int i erreicht ist - also auch nur bis zur max. Länge eines Integers.

PatkIllA
2010-01-11, 22:36:36
Rahmen? Erstsemester Wirtschaftsinformatik.

Die for-Schleife kann doch aber auch nur so oft durchlaufen, bis die maximale Länge von int i erreicht ist - also auch nur bis zur max. Länge eines Integers.
Du kannst 2^31 stellige Zahlen damit erfassen. Das wird bei der Lösung das kleinste Problem sein, wenn man es für mehr als Anschauungszwecke benutzen möchte.

Pinoccio
2010-01-12, 10:34:56
Rahmen? Erstsemester Wirtschaftsinformatik.Aha.
Die for-Schleife kann doch aber auch nur so oft durchlaufen, bis die maximale Länge von int i erreicht ist - also auch nur bis zur max. Länge eines Integers.Du könntest auch long nehmen, wenn es notwendig ist.
Wie groß String werden darf ist in der Sprachdefinition nicht beschränkt. Aber Suns JVM API nutzt einen Charakterarray mit zwei Einträgen pro Einzelzeichen. Arrays sind auf int als Index beschränkt, also kannst du maximal 2^31 Stellen so behandeln, die dann 4 GiB Speicherplatz belegen würden (Da ein Char 2 Byte belegt). Auf Desktopsystemen hat die JVM aber i. d. R. nichtmal so viel Speicherplatz zur Verfügung. int ist also in diesem Beispiel mehr als auseichend.

mfg

Gast
2010-01-24, 09:23:36
Kleiner Tip zur Lektüre:
Java ist eine Insel

Tesseract
2010-01-24, 14:29:50
ein paar anmerkungen:

- ist es absicht, dass die meisten methoden default-sichtbarkeit haben? hier würde man eigentlich protected oder public nehmen, je nach dem für was die methode gedacht ist. (in deinem fall wahrscheinlich alle public)
- müsst ihr den code kommentieren? wenn ja müssen da eventuell zusicherungen rein was passiert, wenn lower > upper und solche dinge.
- ich bin mir jetzt nicht sicher ob das bei java auch der fall ist aber in der regel ist double auf modernen systemen schneller als float, daher sollte man float eigentlich nur noch nehmen, wenn es aus kompatiblitätssicht nötig ist.

Coda
2010-01-24, 17:48:25
double ist auf modernen Systemen ganz bestimmt nicht schneller als float.

Tesseract
2010-01-24, 18:55:51
double ist auf modernen Systemen ganz bestimmt nicht schneller als float.

probier es aus. in c++ mit gcc auf einem core2 ist es z.B. total deutlich. sowohl unter 32 als auch 64 bit.

Abnaxos
2010-01-24, 20:26:41
Wenn double schneller als float ist, wird die JVM sich darum kümmern. Das sind Gedanken, die man sich bei der Java-Programmierung nicht machen sollte, das ist meist kontraproduktiv.

Pinoccio
2010-01-24, 21:35:19
Wenn double schneller als float ist, wird die JVM sich darum kümmern. Das sind Gedanken, die man sich bei der Java-Programmierung nicht machen sollte, das ist meist kontraproduktiv.Die JVM wird alles, was als float typisiert wurde auch als float berechnen. Schließlich ist (float) (1.0f-0.9f) ungleich (float) (1.0d-0.9d).
(float)(1.0f-0.9f) = 0,10000002384185791
(float)(1.0d-0.9d) = 0,10000000149011612
(double)(1.0d-0.9d) = 0,09999999999999998

mfg

Coda
2010-01-24, 21:51:45
probier es aus. in c++ mit gcc auf einem core2 ist es z.B. total deutlich. sowohl unter 32 als auch 64 bit.
Das brauch ich nicht ausprobieren, weil es einfach Nonsense ist. Float ist kleiner im Speicher und die Instruction-Latenzen sind auch geringer.

Was GCC da genau für Müll baut weiß ich nicht.

Abnaxos
2010-01-25, 13:03:39
Die JVM wird alles, was als float typisiert wurde auch als float berechnen. Schließlich ist (float) (1.0f-0.9f) ungleich (float) (1.0d-0.9d).
Das ist irrelevant, denn die Ergebnisse sind alle falsch. Man muss bei Fliesskommazahlen immer damit rechnen, dass die Ergebnisse nicht 100% korrekt sind, wie falsch genau sie sind, kann auch von Architektur zu Architektur variieren. Daher hat Java ja auch den «strictfp» Modifier, der (u.U. auf Kosten der Performance) ein definiertes Verhalten erzwingt.

Pinoccio
2010-01-25, 14:01:01
Das ist irrelevant, denn die Ergebnisse sind alle falsch. Man muss bei Fliesskommazahlen immer damit rechnen, dass die Ergebnisse nicht 100% korrekt sind, wie falsch genau sie sind, kann auch von Architektur zu Architektur variieren. Daher hat Java ja auch den «strictfp» Modifier, der (u.U. auf Kosten der Performance) ein definiertes Verhalten erzwingt.Vermutlich reden wir aneinander vorbei, aber natürlich sind die Ergebnisse falsch.


sOT:
Google: sin(10^300) = -0.409692664 (http://www.google.de/search?q=sin%2810^300%29)
Wolframalpha: sin(10^300) = -0.98575042 (http://www.wolframalpha.com/input/?i=sin%2810^300%29)
JAVA Math.sin(Math.pow(10,300))= -0.817881


mfg

EGG-Beater
2010-01-25, 15:17:34
(float)(1.0f-0.9f) = 0,10000002384185791
(float)(1.0d-0.9d) = 0,10000000149011612
(double)(1.0d-0.9d) = 0,09999999999999998


Und wie macht man es richtig? So, dass 0,1 raus kommt?

Pinoccio
2010-01-25, 15:35:26
Und wie macht man es richtig? So, dass 0,1 raus kommt?Mit binary floating point? Garnicht. (http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems) ;)
Entweder mit einem dezimalen Fest- oder Gleit-Komma-Format oder einem Format, das die Rationale Zahlen nachbildet (bis zu einer bestimmten StellenZahl für p und q).

mfg

Abnaxos
2010-01-25, 15:39:23
Vermutlich reden wir aneinander vorbei, aber natürlich sind die Ergebnisse falsch.


sOT:
Google: sin(10^300) = -0.409692664 (http://www.google.de/search?q=sin%2810^300%29)
Wolframalpha: sin(10^300) = -0.98575042 (http://www.wolframalpha.com/input/?i=sin%2810^300%29)
JAVA Math.sin(Math.pow(10,300))= -0.817881
Eben das meine ich. Beim Umgang mit Fliesskommazahlen musst du mit Fehlern rechnen, das liegt in der Natur von Fliesskommazahlen. Gleichzeitig sind diese Fehler nicht vorhersagbar, weil sie von der Implementation abhängen (Library, CPU, whatever). Daher hat Java den Modifier «strictfp», um eine bestimmte in der JLS festgelegte Implementation zu erzwingen und damit auch vorhersagbare Ergebnisse zu erhalten (soll heissen: plattform- und architekturunabhänige Fehler). In den meisten Fällen dürfte das dann aber auf eine Software-Implementation hinaus laufen.

Aus diesem Grund, weil man mit Fehlern rechnen muss und diese nicht vorhersagbar sind, ist dein Hinweis, dass (float)(1.0-.9) != 1.0f-.9f ist, irrelevant. Wenn die JVM aus Performance-Gründen beschliesst, mit double statt mit float zu rechnen, soll sie das tun – ausser, die Variablen sind eben als «strictfp» deklariert.

Und wie macht man es richtig? So, dass 0,1 raus kommt?
Nicht mit Fliesskommazahlen arbeiten:

System.out.println(new BigDecimal(1).subtract(new BigDecimal("0.9")));

Man beachte den String bei der 0.9. übergebe ich die 0.9 als double an den Konstruktor von BigDecimal, lautet das Ergebnis 0.09999999999999997779553950749686919152736663818359375 ;)

Pinoccio
2010-01-25, 16:03:04
Eben das meine ich. Beim Umgang mit Fliesskommazahlen musst du mit Fehlern rechnen, das liegt in der Natur von Fliesskommazahlen. Gleichzeitig sind diese Fehler nicht vorhersagbar, weil sie von der Implementation abhängen (Library, CPU, whatever). Daher hat Java den Modifier «strictfp», um eine bestimmte in der JLS festgelegte Implementation zu erzwingen und damit auch vorhersagbare Ergebnisse zu erhalten (soll heissen: plattform- und architekturunabhänige Fehler). In den meisten Fällen dürfte das dann aber auf eine Software-Implementation hinaus laufen.

Aus diesem Grund, weil man mit Fehlern rechnen muss und diese nicht vorhersagbar sind, ist dein Hinweis, dass (float)(1.0-.9) != 1.0f-.9f ist, irrelevant. Wenn die JVM aus Performance-Gründen beschliesst, mit double statt mit float zu rechnen, soll sie das tun – ausser, die Variablen sind eben als «strictfp» deklariert.Ah, ich verstehe was du meinst.

mfg

EGG-Beater
2010-01-25, 16:58:20
Mit binary floating point? Garnicht. (http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems) ;)
Entweder mit einem dezimalen Fest- oder Gleit-Komma-Format oder einem Format, das die Rationale Zahlen nachbildet (bis zu einer bestimmten StellenZahl für p und q).

Ok, Verständnisproblem. Was ist denn an irgendeinem nicht-float/double-Typen mehr dezimal als an float/double? Die werden doch alle binär repräsentiert.

Und mit "dezimales Fest- oder Gleitkomma-Format" ist z.B. dieses BigDecimal gemeint?

Pinoccio
2010-01-25, 18:11:30
Ok, Verständnisproblem. Was ist denn an irgendeinem nicht-float/double-Typen mehr dezimal als an float/double? Die werden doch alle binär repräsentiert.Naja, letzendlich wird das intern schon binäre verarbeitet, aber z. B. IEEE 854 (http://754r.ucbtest.org/standards/854.html) spezifiziert auch dezimale Gleitkommazahlen. Das entspricht (bis auf Beschränkungen hinsichtlich der Größe) der sog. Wissenschaftlichen Notation, d.h. 0,1 wird intern als + 1 * 10^(-1) (= 1e-1) gespeichert und 0,9 als ebenso genau exakt als + 9 * 10^(-1) (=9e-1) . Nach außen hin ist es also nicht-binär.
Damit kann man aber natürlich Brüche wie 1/3 auch nciht exakt speichern.
Und mit "dezimales Fest- oder Gleitkomma-Format" ist z.B. dieses BigDecimal gemeint?Ja, BigDecimal (http://java.sun.com/javase/6/docs/api/java/math/BigDecimal.html) ist ein solches dezimales Gleitkommaformat, es ist in der Standard-JAVA API enthalten. A BigDecimal consists of an arbitrary precision integer unscaled value and a 32-bit integer scale, d.h. der abgedeckte Zahlenbereich ist schon enorm.

Die aktuell beste bekannte Approximation von Pi (http://www.heise.de/newsticker/meldung/Pi-Berechnungsrekord-auf-handelsueblichem-PC-899930.html) würde allerdings nicht mehr reinpassen, da die 2.699.999.990.000 Nachkommastellen nicht mehr mit mit 10^int skaliert werden können.
Dafür gibt es dann aber extra Bibliotheken, die das auch noch machen könnten (zumal BigDecimal vergleichsweise lahm ist).

mfg

Coda
2010-01-25, 18:18:21
Das ist irrelevant, denn die Ergebnisse sind alle falsch.
Nö, nicht zwangsläufig. Alle ganzen Zahlen die in die Mantisse passen werden z.B. genau repräsentiert.

Pinoccio
2010-01-25, 18:33:05
Nö, nicht zwangsläufig. Alle ganzen Zahlen die in die Mantisse passen werden z.B. genau repräsentiert.Natürlich kann man mit float und double auch exakt rechnen, 0.5+0.5*4 z. B. wird exakt ausgerechnet, ebenso im Bereich der passenden ganzen Zahlen. Aber die 3 Beispiele sind so immer falsch.

mfg

pest
2010-01-25, 19:12:11
sry für ot


Die 50 Nachkommastellen ab der 2.699.999.989.951ten lauten übrigens 9256371619 3901058063 3448436720 6294374587 7597230153. Gut, dass man das jetzt endlich mal weiß.


die kennen die BBP-Reihen (http://de.wikipedia.org/wiki/Kreiszahl#BBP-Reihen) noch nicht

Coda
2010-01-25, 20:29:41
sry für ot



die kennen die BBP-Reihen (http://de.wikipedia.org/wiki/Kreiszahl#BBP-Reihen) noch nicht
Du bist fies ;)

pest
2010-01-25, 20:58:10
nicht wirklich, wenn man bedenkt das die c't in einem Artikel der gefühlte 10 Jahre her ist, diese Reihen vorgestellt haben.

The good ol' times :(

Tesseract
2010-01-25, 22:50:25
Natürlich kann man mit float und double auch exakt rechnen

float und double rechnen immer "exakt" wenn die CPU nicht kaputt ist. falsch ist lediglich die annahme, es würde sich dabei um reale zahlen handeln.

PatkIllA
2010-01-25, 22:54:54
float und double rechnen immer "exakt" wenn die CPU nicht kaputt ist. falsch ist lediglich die annahme, es würde sich dabei um reale zahlen handeln.
Was sind denn reale Zahlen? Du meinst reele Zahlen oder?
Mit Gleitkomma kannst du ja gerade mal einen endlich abzählbaren Teilbereich der rationalen Zahlen genau darstellen. Wie kannst du damit immer exakt rechnen?

Tesseract
2010-01-25, 22:56:33
Was sind denn reale Zahlen? Du meinst reele Zahlen oder?

ja natürlich. ich hab das jetzt im hirn mit den englischen "real numbers" durcheinandergewürfelt. :D

Pinoccio
2010-01-25, 22:56:52
float und double rechnen immer "exakt" wenn die CPU nicht kaputt ist. falsch ist lediglich die annahme, es würde sich dabei um reale zahlen handeln.Werter Herr Haarspalter, was sind denn reale Zahlen? Solche die man anfassen kann, welche mit Geschmack? :freak:

/edit: Achso, reelle Zahlen meintest du ...

Wie kannst du damit immer exakt rechnen?Die Computerzahlen bilden keinen Körper, nichteinmal eine Gruppe. Trotzdem gibt es Abbildungen auf dieser Menge. Mit einer gewissen Abstraktion kann man denen die Namen Addition etc. geben und dann behaupten, man rechne. :ugly: Für die grundlegenden Operationen sind die Ergebnisse sogar "exakt" i. S. v. bestmöglich.
Vgl. O. Forster: Analysis 1, Seite 48ff

mfg