Double-Zahlen auf Intervalle runden

Michel95

Mitglied
Hallo,
Ich programmiere gerade an einem Funktionsplotter in Java, und ich möchte an der x- und y-Achse eine Skala anzeigen, das heißt einfach gesagt ich habe einen Sichtbereich von z.B. -3.0 bis 3.0 und einen Intervall von 0.5, die Zahlen die ich dann schrittweise berechne wären in diesem Fall -3.0, -2.5, ... 0.0, ... 2.5, 3.0.

Das ganze kann ich rein- und rauszoomen, dabei wird der Intervall immer so berechnet, dass es eine "glatte" Zahl, z.B 0.2 ergibt.

Soweit funktioniert alles super, nur wenn ich die Skalabeschriftung auf den Bildschrim zeichne, tauchen dabei manchmal fehlerhafte Zahlen auf, die sehr unschön aussehen. Statt 0.6 erscheint manchmal 0.6000000000000001, wahrscheinlich aufgrund von kleinen Rechenfehlern. Oder statt 10.0 erscheint der Wert 9.999999999999999.

Ich habe schon versucht, mir mit einer round() Methode zu helfen, die auf die Intervalle rundet:

Java:
public double round(double value, double intervall) {
		double d1 = value / intervall;
		long anz = Math.round(d1);
		System.out.println(anz * intervall);
		return anz * intervall;
	}

Leider liefert die Methode auch solche krummen werte.
Ich habe auch versucht mit Decimal Format zu formatieren, aber habe auch keine Ergebnisse hinbekommen. Gibt es irgendeine saubere Methode, um die Double-Zahlen auf Intervalle zu runden, das heißt bei einem Intervall von 0.2 soll die Zahl 0.6000000000000001 auf 0.6 abgerundet werden?

Ich wäre sehr dankbar für eine hilfreiche Antwort!
 
Der Fehlerursprung ist die Fließkommazahl. Evtl. musst du den Datentyp wechseln, um diese Nachkommafehler nicht zu erhalten. Versuch mal BigDecimal.
 
Evtl. bietet "String.format()" die richtigen Möglichkeiten dafür wenn man die Anzahl der Vor- und Nachkommastellen festlegt. z.B. "String.format("%1.2f", 0.60000001)"
 
Danke für deine Antwort, ich weiß noch nicht genau, wo ich jetzt den DigDecimal einbauen soll.
Dashier ist mein Code:

Java:
g.drawLine(0, (int) delta.y, width, (int) delta.y);
			
			double anzSkalierungen = width / 1000.0; // bei 600 px 600 / 100.0 = 6 Markierungen an der Skala
			double skalierungGroesse = size.x / anzSkalierungen; // bei 6 Markierungen und Breite 20 = 20 / 6 = 3.33 Einheiten Skalierabstand
			double d = Math.abs(skalierungGroesse); // Zahl zwischen 1.0 und 10.0
			double factor = 1.0; 
			if (d < 1.0) while (d < 1.0) { d *= 10; factor *= 10; }
			else if (d > 10.0) while (d > 10.0) { d *= 0.1; factor *= 0.1; }
			d *= 0.1;
			if (d < 0.2) d = 0.1;
			else if (d < 0.5) d = 0.2;
			else if (d < 1.0) d = 0.5;
			else { d = 0.1; factor *= 0.1; }
			skalierungGroesse = d / factor;
			anzSkalierungen = size.x / skalierungGroesse;
			double x = delta.x % (skalierungGroesse * zoom.x);
			double y = delta.y;
			if (y < 5) y = 5;
			else if (y > height - 50) y = height - 50;
			double skalaWert = viewBeginn.x + x / zoom.x;
			for (int i = 0; i < anzSkalierungen; i++) {
				int lx = (int) (x + skalierungGroesse * zoom.x * i);
				g.drawLine(lx, (int) (y - 5), lx, (int) (y + 5));
				g.drawString(Double.toString(round(skalaWert, skalierungGroesse)), lx, (int) (y + 20));
				skalaWert += skalierungGroesse;
			}

Soll ich einfach mal alle double durch BigDecimal ersetzen?
 

Zurück
Oben