Zahlenformat für unendliche Brüche?

sildave94

Mitglied
Hallo zusammen

Ich arbeite momentan an etwas Uhr-ähnlichem, wobei ich nun ein Problem habe. Der Code sieht folgendermassen aus (ich habe ihn auf das für dieses Problem Wesentliche reduziert):

Java:
double h = 15;
while(true){
h = h + (5/60);
System.out.println(h);
x = cos(h * (-2 * Math.PI / 60) – 0.5 * Math.PI) * 50;
y = sin(h * (-2 * Math.PI / 60) – 0.5 * Math.PI) * 50;
}

Die Variable double h sollte also bei jedem Schleifendurchlauf um 5/60 erhöht werden, was unten wiederum den Winkel verändert und im Grunde genommen dazu führt, dass ein Punkt einen Kreisumfang entlangwandert. Allerdings bewegt sich dieser Punkt keinen Millimeter und auch der Output für h ist immer 15.0. Es sind noch weitere solcher Punkte mit genau demselben Code im Spiel, deren Variable sich immer um 1.0 erhöht, die funktionieren jedoch einwandfrei.

Aus irgendeinem Grund habe ich dann mal versucht, 5/60 durch 0.0833333333 zu ersetzen, was die Gewünschte Bewegung zur Folge hatte, jedoch ergibt sich dadurch natürlich eine gewisse Ungenauigkeit. So sollte h nach 60 Durchläufen theoretisch 20.0 sein, ist aber nur 19.999999998000035.

Die Abweichung ist zwar sehr gering und man könnte z.B. alle 60 Durchläufe eine Korrektur vornehmen, jedoch möchte ich, vor allem aus Lerngründen, gerne wissen, weshalb es mit 5/60 nicht klappt. Sollte ich ein anderes Zahlenformat wählen als double? Wenn ja, welches? Oder hat das eine ganz anderen Grund?

Ich bin euch dankbar für jede Hilfe und wünsche schöne Weihnachten
Silas
 
double ist leider sehr ungenau... gerade bei sowas...

du koenntest dir ein eigenes Format ausdenken - aus Lerngruenden waere sowas denkbar
class Bruch

diese Klasse hat einen Nenner und einen Zaehler und kann das Ergebnis in verschiedenen Formaten zurueckliefern

du kannst nun immer mit einem Bruch statt mit einem double arbeiten, und fragst den bruch nur in bestimmten Faellen nach einem double, oder einem BigDecimal

die Klasse Bruch kann zum Beispiel auch noch anbieten, Brueche zu berechnen:
public Bruch addieren(Bruch links + Bruch rechts) (usw fuer alle Grundrechenarten usw.)
 
wie pentalon schon richtig sagte ist die lösung hier

"(5.0d/60.0d)"

grund : 5 und 60 werden so als INT betrachtet ... und in java gilt : INT / INT = INT ... und darum wird aus 0.83 halt schlicht 0 ... wesshalb dann am ende dasteht : h + 0
um also bei einer devision keinen INT zu bekommen sondern eben einen float/double muss mindestens einer der operanden ein float/double sein ...
dies wird erreicht in dem man ".0" anhängt ... wenn man zusätzlich noch das suffix "d" für double angibt wird es ganz eindeutig ... denn "5.0" kann auch ein float sein ...

alternativ könnte man auch mit BigDecimal arbeiten ... da aber sicher damit noch irgendwie gezeichnet werden soll ... und man daher eh double braucht ... kann man auch gleich mit double arbeiten ...

BigDecimal verwendet man eher zum rechnen ...

@Phash
grundsätzlich wäre aber zu beachten das man mit gleitkommazahl-datentypen arbeitet ... also float/double bzw BigDecimal ... denn wenn man intern z.b. zwei INTs hat ... und dann einfach schreibt "return intA/intB" kommt wieder nur ein INT raus ... was dann halt zu ungenau wird ...
 
Super, vielen Dank für eure Hilfe!!

Ich werde den Fehler erstmal so beheben, wie Pentalon dies vorgeschlagen hat und mich dann durch die vielen weiteren Lösungen arbeiten 😀

Danke & Gruss
 
Ich denke, hier sollte man auch die Festkommanotation erwähnen, als Lösungsmöglichkeit. Da der Bruch immer den selben Nenner hat (60), kann man auch einfach nur den Nenner als int speichern und vor der Verwendung dann durch 60.0 teilen. Da int keine Rundungsungenauigkeiten besitzt, wie double und float, kann sich der Fehler nicht auf summieren, sondern man hat immer die Genauigkeit von 1 ulp.

So wird das z.B. auch häufig beim rechnen mit Währungen gemacht. Man speichert den Wert als Cents in einem int/long und teilt dann durch 100.0 um den Euro-Betrag zu erhalten.
 
Nicht gut, weil sich hierbei der Fehler immer weiter aufsummiert:
Java:
double h = 15;
while (true) {
	h = h + (5/60D);
}

Besser:
Java:
double h;
for (int i = 0;; i++) {
	h = (15 + i * 5 / 60D) % periode;
}
 

Zurück
Oben