Java Java Verständnis Schwierigkeitn beim rechnen mit float Datentypen

Zespire

Lieutenant
Registriert
März 2007
Beiträge
857
Grüße der Zeit stellt sich mir Folgendes Problem ich will ein paar Rechenoperationen mit floats durchführen, nur leider habe ich Schwierigkeiten bei der Addition.

Hier mal mein Test Programm...
Code:
 public class TestMain {
	
	public static void main(String ARGS[]){
		String newLine = System.getProperty("line.separator");
	//	float geschwindigkeit =     2.4999172E-4f;
		float beschleunigung  =     8.3134495E-9f;
		float zeit			  =    60.0f;
		float x	  	  		  =     1.0f;
		float y				  = (beschleunigung*(zeit*zeit)/2f);
		
		System.out.println(y + newLine);
		
		for(int i = 5 ; i != 0 ; i--){
			x += y;
			System.out.println(x);
		}
		
		x	  =     0f;
		System.out.println("");
		
		for(int i = 5 ; i != 0 ; i--){
			x += y;
			System.out.println(x);
		}
	}
}


und hier was er mir ausgibt.

1.4964209E-5

1.000015
1.00003
1.0000451
1.0000601
1.0000751

1.4964209E-5
2.9928418E-5
4.489263E-5
5.9856837E-5
7.4821044E-5

Meine Frage ist wie kommen die Ergebnisse zustande, müsste nicht Oben 2.5 , 4 , 5.5 und so weiter raus kommen ?
 
Hallo,

das E-5 in 1.4964209E-5 steht für eine Zehnerpotenz, nämlich 10^-5. Das bedeutet, dass dein y = 1.4964209 * 10^-5 ist, also ~0.00001496.
Aufgrund der Ungenauigkeit bei Floats wird dann auch nicht immer exakt 0.00001496 aufaddiert, daher der Schritt 1.00003 -> 1.0000451.
 
Zuletzt bearbeitet:
Du weist, dass E-5 = 10^-5 ist?

Passt alles der obere Block ist ja einfach der untere + 1, da du ja einmal mit x=1 und einmal mit x=0 beginnst.
 
Ich sags immer wieder: Ich hasse Potenzen ;P
y = 0.0000149642092 sollte wohl alles erklären^^
Btw. im Debuggen wenn du die variable anzeigst sollte es als "richtige" Zahl angezeigt werden, dann hättest du es sofort gesehen...

Edit:
Aus dem y mal ein 1.0000149642092 gemacht, dann kommt ungefähr das raus was du wolltest:

2.000015
3.00003
4.000045
5.00006
6.000075

1.000015
2.00003
3.000045
4.00006
5.000075
 
Dachte schon das ich mich total zum Affen mache mit der Frage ;D
ich ging davon aus das sich das E-x auf die Anzahl der Nachkommastellen bezieht.
 
Aber 7.4821044E-5 hat doch mehr als 5 Nachkommestellen ^^ Trotzdem kein Problem, manchmal sind die kleinen Probleme die, an denen man sich am meisten aufhält :)
 
Danke für die Antworten hier mein Eigentliches Problem


Code:
public void getComputerTarget(){

		start.clear();
		end.clear();
		boolean noTarget = true;
		short vectorCount = 0;
		int	 angle = (int) Main.ball.angle;
		
		start.add(new vector());
		vector startPoint = start.get(vectorCount);
		startPoint.set(Main.ball.position.x+7, Main.ball.position.y+7);
		
	
		while(noTarget){
			
			end.add(new vector());
			vector targetPoint = end.get(vectorCount);
			targetPoint.set(startPoint.x,startPoint.y);

			while(targetPoint.x >= x && targetPoint.x <= endx && targetPoint.y >= y && targetPoint.y <= endy ){

				targetPoint.x  	+= (2 * (Math.cos(Math.toRadians(angle))));
				targetPoint.y  	+= (2 * (Math.sin(Math.toRadians(angle))));
			

				targetPoint.x   +=(float) (Main.ball.test.x*(GameLoop.publicFPS*GameLoop.publicFPS)/2f)*(Main.ball.velocity.x/GameLoop.publicFPS);
				targetPoint.y   +=(float) (Main.ball.test.y*(GameLoop.publicFPS*GameLoop.publicFPS)/2f)*(Main.ball.velocity.y/GameLoop.publicFPS);
				
			}
			System.out.println(targetPoint.y);

			if(targetPoint.x >=endx -7|| targetPoint.x == endx){

				targetPoint.x -= 25;
				finish.set(targetPoint.x, targetPoint.y);
				noTarget = false;
			}else{
				if(targetPoint.x >= endx -7){
					targetPoint.x -= 10;
					angle = 180 - angle;
				}
				if(targetPoint.x <= x +7){
					targetPoint.x += 10;
					angle = 180 - angle;
				}
				if(targetPoint.y >= endy -7){
					targetPoint.y -= 10;
					angle = 360 - angle;
				}
				if(targetPoint.y <= y +7){
					targetPoint.y += 10;
					angle = 360 - angle;
				}
				
				if(angle % 25 == 0){
					angle += 1;
				}
				if(noTarget){
					vectorCount ++;
					start.add(new vector());
					startPoint = start.get(vectorCount);
					startPoint.set(targetPoint.x, targetPoint.y);
				}	
			}		
		}
		
		drawstart = start;
		drawend	  = end;
	}

Ich berechne hier die Flugbahn des Balles damit der Computer weiß wohin er sich bewegen soll.

Dabei habe ich das Problem das mit zunehmender Geschwindigkeit die Genauigkeit abnimmt.

Ich habe mal das Programm im Anhang hochgeladen man muss es etwas laufen lassen um zu sehen was ich meine...
 

Anhänge

  • test.rar
    83,5 KB · Aufrufe: 82
Ich habe leider gerade nicht die Zeit, das Programm laufen zu lassen, deshalb kann ich nur schnell versuchen eine Erklärung zu liefern:

Gleitkommazahlen wie floats haben nur eine beschränkte Genauigkeit. Insbesondere können auch manche dezimalen Zahlen überhaupt nicht genau als Gleitkommazahl dargestellt werden (z. B. 0,3). Richtig problematisch wird es, wenn die Zahlen sehr weit auseinander liegen. Dann kann es vorkommen, dass a+b=a gilt (z. B. a sehr groß, b sehr klein)! In diesem Fall ist sogar die Berechnungsreihenfolge entscheidend, da unter Umständen ((a+b)+b)+... nicht gleich a+(b+(b+b+...) ist.

Aus diesem Grund solltest du dich nicht über Ungenauigkeiten in der Berechnung wundern. Falls dir die Päxision von float nicht reicht, kannst du einfach mal versuchen, ob double bessere Ergebnisse liefert.

EDIT: oder du nutzt die Klasse BigDecimal. Die sollte genaue Ergebnisse liefern, ist aber natürlich nicht so performant wie die primitiven Datentypen.

Ich hoffe, ich habe jetzt nicht vollkommen an deinem Problem vorbei geredet.
 
Warum machst du aus dem Winkel eine Ganzzahl?
Code:
int	 angle = (int) Main.ball.angle;

Das steigert die Ungenauigkeit, sieht man sehr schön, das der Winkel nicht immer ganz stimmt. Das Problem wird gravierender wenn die Geschwindigkeit hoch ist, da sich dort die Ungenauigkeit vervielfältigt.

Warum machst du hier noch ein cast zu (float)? Sind Main.ball.velocity.x und/oder GameLoop.publicFPS zufällig Ganzzahlen?
Code:
targetPoint.x   +=(float) (Main.ball.test.x*(GameLoop.publicFPS*GameLoop.publicFPS)/2f)*(Main.ball.velocity.x/GameLoop.publicFPS);
targetPoint.y   +=(float) (Main.ball.test.y*(GameLoop.publicFPS*GameLoop.publicFPS)/2f)*(Main.ball.velocity.y/GameLoop.publicFPS);
 
Danke an die beiden Antworten über mir.

Der cast zu float bei meinem Ziel Vector war noch ein Überbleibsel von vorherigen Versuchen.

Wieso ich den Winkel zu Int gecastet habe weiß ich nicht, aber jetzt wo er float ist scheint es schon einmal besser zu funktionieren ;)

[Edit]: Also es lag wirklich an dem cast zu Int beim Winkel.

Mein Gedanke war es liegt an der Beschleunigung deswegen Wollte ich ich den Faktor (Weg-Zeit) mit ein beziehen, was eigentlich total blöd von mir war da bei mir der Eintrittst Winkel = Austritts Winkel ist.

Dadurch ist es egal in welcher Zeit er welche Strecke zurücklegt da es nur um die ein und austritst Punkte geht ...

Und das alles nur wegen (int) :freaky:

[Edit2]: Zur besseren Verständlichkeit

Code:
    targetPoint.x +=(float) (Main.ball.test.x*(GameLoop.publicFPS*GameLoop.publicFPS)/2f)*(Main.ball.velocity.x/GameLoop.publicFPS);
    targetPoint.y +=(float) (Main.ball.test.y*(GameLoop.publicFPS*GameLoop.publicFPS)/2f)*(Main.ball.velocity.y/GameLoop.publicFPS);

sollte anstelle der 2 bei

Code:
targetPoint.x += (2 * (Math.cos(Math.toRadians(angle))));
targetPoint.y += (2 * (Math.sin(Math.toRadians(angle))));

herhalten .
 
Zuletzt bearbeitet:
Zurück
Oben