Java-Gaming.org    
Featured games (91)
games approved by the League of Dukes
Games in Showcase (581)
games submitted by our members
Games in WIP (500)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: 1 2 [3] 4 5
  ignore  |  Print  
  Mathematical vectors  (Read 12833 times)
0 Members and 1 Guest are viewing this topic.
Offline lhkbob

JGO Knight


Medals: 32



« Reply #60 - Posted 2011-04-07 03:22:50 »

Oops, I hadn't seen the negative sign before.  (cos (angle), sin(angle)) is perpendicular to (sin(angle), -cos(angle)).  Your original code didn't have the negative, but deadly72 added it in (I'm not sure why).

Offline deadly72

Junior Member





« Reply #61 - Posted 2011-04-07 04:20:38 »

1  
To get the angle do I need to normalize the vector first? If so it should be pretty simple giving

no, but do you notice it is radian not degree ?


1  
Oh, and a quick side note: I've seen so many people use floats instead of doubles for positioning.  Whats the reasoning behind it and should I change the variables to represent floats instead?

nowadays float is better suitable for hardware, but personnaly I prefer double as it give a lot higer resolution than float and enable NaN (matematical unresolvable) gesture

I wasn't too sure about it being a radian or degree Tongue should have checked the api, my bad Smiley.  Thanks for the info on the float.  I wasn't sure about using it since it would just make a few operations require typcasting from double to float... so I guess I will just use doubles Smiley
This was code ra4king gave you a bit ago and you've been using it since, but it has a bug in it.
1  
2  
3  
4  
...
velocity = new Vector2D(Math.sin(Math.toRadians(carAngle)) * (currentSpeed * deltaSeconds), -Math.cos(Math.toRadians(carAngle)) * (currentSpeed * deltaSeconds));
position = Vector2D.add(position, velocity);
...


If you're creating an (a, b) vector from an angle (in this case, carAngle) and magnitude (in this case, currentSpeed * deltaSeconds) you want to have (a, b) = (magnitude * cos(angle), magnitude * sin(angle)) but right now you have them swapped and are using sin in your x coordinate's equation, and cos in your y's.

As DzzD hinted at, Math.atan2 and Math.atan return angle values in radians and not degrees. If you want degrees, just use Math.toDegrees(Math.atan2(y, x)).

Also, you do not need to normalize the vector before getting the angle.  Math.atan and Math.atan2 both compute the arctan function, which in math takes a single scalar: arctan(y / x).  If m is the magnitude of (x, y), then arctan( (y/m) / (x/m) ) = arctan( (y / x) * (1/m)/(1/m) ) = arctan(y / x)

Math.atan2 separates the arguments so you don't accidentally divide by 0 and you can use the signs on y and x to determine which quadrant the angle should be in.

Alright so getting the angle is fixed formula wise, but, but if I do the vector your way (with mag * cos(angle), and mag * sin(angle) for y ) my movement becomes messed up.  For example pressing up and down keys now generate movement along the x axis instead of up and down respectively as they did before.  If this is the proper way to do it, (and we can't emulate motion using up and down keys for north and south) then the only solution I can think of is that I need to change my sprite direction to face east at the beginning instead of north as it does currently.

As far as why I added -cos in the equation was for motion so when I pressed the up arrow the car would travel up the y axis instead of going down, as it does when you increase y.
Offline ra4king

JGO Kernel


Medals: 322
Projects: 2
Exp: 4 years


I'm the King!


« Reply #62 - Posted 2011-04-07 04:23:58 »

As far as why I added -cos in the equation was for motion so when I pressed the up arrow the car would travel up the y axis instead of going down, as it does when you increase y.
Oh makes sense Smiley

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline jezek2
« Reply #63 - Posted 2011-04-07 06:22:05 »

nowadays float is better suitable for hardware, but personnaly I prefer double as it give a lot higer resolution than float and enable NaN (matematical unresolvable) gesture

Float has the same behaviour as double (including the NaNs). For any normal usage floats are more than sufficient and more efficient (remember JVM and any modern compiler uses SSE instructions that have native support for floats and not the FPU code which computes in 80bit on Intel). Only for some special cases such as scientific usage doubles can be better, but then they're still floating point so many mathematical properties do not hold.

Generally when you reach limits of floats you have some bigger problem. Eg. if you have some really big world it's often better to do some partitioning and streaming anyway because it wouldn't fit into the memory or the GPU renderer (which uses floats only) couldn't represent it. Also 64bit fixed point might be better for representation in that case as it has the same precision over the whole range.

Another example is physics engines, you will hit the precision error due to solver being just crude approximation (otherwise it wouldn't be realtime) much sooner than you'll hit precision error due to floats.
Offline DzzD
« Reply #64 - Posted 2011-04-07 09:10:44 »

using double can save of a lot of headhack when dealing with mathematic, floatting (float, double etc) computation introduce error at each step so the error get amplified, double will juts introduce less errors, even if I do that, I am not arguing to use double all the time but just to be carefull that a floating computation result is often false, for example a simple scalr product on two vector normalized may give a result a little greater than 1 and lead to an error when used later in acos, the risk also exist with double but it is lower

Offline dishmoth
« Reply #65 - Posted 2011-04-07 10:09:50 »

Quote
You can normalize any vector (except the zero vector) by dividing it by its magnitude: (c,d) = (a,b)/sqrt(a*a+b*b).  The result is a unit vector.
Any unit vector can be represented by an angle: (a,b) = (cos(theta),sin(theta)).  The angle theta equals atan2(b,a).
To get the angle do I need to normalize the vector first?
No, you don't need to normalize first.

I was trying to demonstrate that you can always(*) convert
    a vector in component form (x,y)
to or from
    a magnitude together with an angle
or
    a magnitude together with a unit vector
which makes the point that you can represent a direction by either an angle or a unit vector.

Simon

(* The zero vector is a bit tricky, but let's not worry too much about that.)

Offline dishmoth
« Reply #66 - Posted 2011-04-07 10:52:49 »

Oops, I hadn't seen the negative sign before.  (cos (angle), sin(angle)) is perpendicular to (sin(angle), -cos(angle)).  Your original code didn't have the negative, but deadly72 added it in (I'm not sure why).
That may have been my fault. Lips Sealed

In deadly's original thread, that combination of sin and cos made the movement code consistent with the drawing code.  Since the movement code was causing problems but the drawing code wasn't, it seemed more practical at the time not to bother debugging the drawing code, even though its use of angles was going against convention.

The (sin,-cos) in the movement code can be switched for the more conventional (cos,sin) so long as the rotation in the drawing code replaces carAngle with (carAngle+90) (errm, or possibly carAngle-90) and the game's initial value of carAngle is similarly changed.

Simon

Offline dishmoth
« Reply #67 - Posted 2011-04-07 11:00:19 »

In addition to getting the angle, I've been trying to figure out how to reverse the direction of the vector (Which should be simple!).  From what I've read it seems that to reverse the direction a simple scaling operation on the vector with negative 1 should do the trick.

I don't get how that works because if you scale a vector with negative 1 you will just have the resulting negative coordinates.

Multiplying by -1 does indeed reverse the vector.  What's wrong with negative values?

The vector (+1,0) points to the right.  Its reverse, the vector (-1,0), points to the left.

I agree that it's not obvious how this works in terms of the vector's angle, but you can trust in atan2 to make sense of it for you. Wink

Simon

Offline ra4king

JGO Kernel


Medals: 322
Projects: 2
Exp: 4 years


I'm the King!


« Reply #68 - Posted 2011-04-07 11:12:19 »

Oh my poor brain.......
I'm too lazy to reread everything here and try to make sense of how exactly Vectors make sense.
I will wait til next year when I am taught vectors at school Grin

Offline pjt33
« Reply #69 - Posted 2011-04-07 14:20:50 »

And this thread made my head hurt. So much confusion back and forth!
This is why I stopped posting. I didn't want to confuse the OP even more than he was already confused.

But having said that...

using double can save of a lot of headhack when dealing with mathematic, floatting (float, double etc) computation introduce error at each step so the error get amplified, double will juts introduce less errors, even if I do that, I am not arguing to use double all the time but just to be carefull that a floating computation result is often false, for example a simple scalr product on two vector normalized may give a result a little greater than 1 and lead to an error when used later in acos, the risk also exist with double but it is lower
Can you justify that assertion about the relative risk of normalising to a value greater than 1 with some actual numerical analysis?
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline DzzD
« Reply #70 - Posted 2011-04-07 14:46:38 »

to answer fast here is a simple sample

Output give :  
Test Double Sum=1000.0000000001588
Test Float Sum= 999.9029

for float error become high very fast up to 0.01% while for double it is still lower than 0.000..01%

ok I know, this is not the best sample as integrating is the worst case for floating values but it is one case...

will try to find another sample using cos, normalisation or such... but basically I ve solved a cupple of software I did just problems by doing a search/replace float/double, it inded doesnt remove bugs but reduce them a lot due to a lot less errors in computations.

about analysis it is just a matter of resolution, I mean this is as evident that with byte you have more risk of capacity overflow than with long


1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
    public static void main(String[] args) 
    {
       
       // TODO, add your application code
      System.out.println("Test Double Sum" + testSumDouble());
       System.out.println("Test Float Sum= " + testSumFloat());
       
    }
   
    public static double testSumDouble()
    {
       double result=0.0;
       for(int n=0;n<10000;n++)
       {
          result+=0.1;
       }
       return result;
    }
   
    public static float testSumFloat()
    {
       float result=0.0f;
       for(int n=0;n<10000;n++)
       {
          result+=0.1f;
       }
       return result;
    }

Offline Roquen
« Reply #71 - Posted 2011-04-07 18:44:32 »

Wow! That's misleading!
Offline Orangy Tang

JGO Kernel


Medals: 51
Projects: 11


Monkey for a head


« Reply #72 - Posted 2011-04-07 19:08:12 »

but basically I ve solved a cupple of software I did just problems by doing a search/replace float/double, it inded doesnt remove bugs but reduce them a lot due to a lot less errors in computations.
Yes, because it's always better to mask bugs and make them harder to reproduce rather than actually doing things properly and fixing them. Roll Eyes

I find your entire suggestion of using doubles rather than floats to be completely disingenuous. Doubles have all the same problems floats do. Misleading newbies as you're doing is just unhelpful IMHO.

More helpfully, here's the obligatory link: http://download.oracle.com/docs/cd/E19957-01/806-3568/ncg_goldberg.html

[ TriangularPixels.com - Play Growth Spurt, Rescue Squad and Snowman Village ] [ Rebirth - game resource library ]
Offline DzzD
« Reply #73 - Posted 2011-04-07 19:17:12 »

Yes, because it's always better to mask bugs and make them harder to reproduce rather than actually doing things properly and fixing them. Roll Eyes

I find your entire suggestion of using doubles rather than floats to be completely disingenuous. Doubles have all the same problems floats do. Misleading newbies as you're doing is just unhelpful IMHO.

More helpfully, here's the obligatory link: http://download.oracle.com/docs/cd/E19957-01/806-3568/ncg_goldberg.html
hehe sorry to have an advice... yes I agree this is not "the best solution" to mask bug,  and anyway errors must be handled in both case double & float but .. for example in a collsion detection float will produce more error => more correction => more grip/stuck => lower quality

(anyway that's true your link is helpfull... too much maybe...)

and finally about double/float, OP have asked about ...

Offline pjt33
« Reply #74 - Posted 2011-04-07 20:37:53 »

about analysis it is just a matter of resolution, I mean this is as evident that with byte you have more risk of capacity overflow than with long
It's obvious that a difference of n ulp is larger in absolute and relative terms for floats than for doubles, but for functions like log or acos where a single ulp past a cutoff value makes the return value change from sensible to NaN it's not the absolute or relative error that matters. I don't think you've justified your statement about dot products at all.
Offline deadly72

Junior Member





« Reply #75 - Posted 2011-04-08 04:13:11 »

Oops, I hadn't seen the negative sign before.  (cos (angle), sin(angle)) is perpendicular to (sin(angle), -cos(angle)).  Your original code didn't have the negative, but deadly72 added it in (I'm not sure why).
That may have been my fault. Lips Sealed

In deadly's original thread, that combination of sin and cos made the movement code consistent with the drawing code.  Since the movement code was causing problems but the drawing code wasn't, it seemed more practical at the time not to bother debugging the drawing code, even though its use of angles was going against convention.

The (sin,-cos) in the movement code can be switched for the more conventional (cos,sin) so long as the rotation in the drawing code replaces carAngle with (carAngle+90) (errm, or possibly carAngle-90) and the game's initial value of carAngle is similarly changed.

Simon

So this was fixed using the standard convention I suppose (cos, sin), by using -90 degrees on the carAngle's inital value.  Does AffineTransform have the east facing as 0 degrees automatically?

I see float vs doubles sparks a big debate, but after having skimmed through Orangy Tang's link I realized that it is really up to the programmers intuition to figure out whats best for the program.

As for scaling the vector to change direction (-1) I do understand what you mean now, so I'm guessing the problem is when I add the velocity vector to position that the desired effect isn't happening (or because I call the move method inside the class which create a new velocity vector and overwrites the one I scaled?).  For example this is what's happening right now.

1  
2  
3  
4  
public void scaleVelocity(int scale) {
   velocity.scale(scale);
   position = Vector2D.add(position, velocity);
}


velocity does reverse coordinates, but the position isn't reversing as expected?
scale just multiplies the current vector by the scalar value.

I'm at a loss as to why this isn't working out the way it's supposed to.

EDIT: Oh and by the way, figuring out the direction was fixed.  Stupid me was trying to get the direction the position vector instead of velocity vector Cranky
Offline DzzD
« Reply #76 - Posted 2011-04-08 10:46:24 »

about analysis it is just a matter of resolution, I mean this is as evident that with byte you have more risk of capacity overflow than with long
It's obvious that a difference of n ulp is larger in absolute and relative terms for floats than for doubles, but for functions like log or acos where a single ulp past a cutoff value makes the return value change from sensible to NaN it's not the absolute or relative error that matters. I don't think you've justified your statement about dot products at all.

as mentioned that was a fast answer, here is another sample :

Output :

V1 (float) = (0.6401844 : 0.7682213)
V2 (float) = (0.6401844 : 0.7682213)
V1.V2 (float) = 1.0000001
Angle (float)= NaN

V1 (double) = (0.6401843996644798 : 0.7682212795973759)
V2 (double) = (0.6401843996644798 : 0.7682212795973759)
V1.V2 (double) = 1.0
Angle (double)= 0.0


Both class VectorFloat & VectorDouble are exacly the same except float / double use

as I was saying you dont get ride of error by using double but you got far away less probabilities of errors


Main :
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
      VectorFloat v1Float=new VectorFloat(500000f,600000f);
       VectorFloat v2Float=new VectorFloat(500000f,600000f);
       v1Float.normalize();
       v2Float.normalize();
       
       VectorDouble v1Double=new VectorDouble(500000.0,600000.0);
       VectorDouble v2Double=new VectorDouble(500000.0,600000.0);
       v1Double.normalize();
       v2Double.normalize();
       
       System.out.println ("V1 (float) = " + v1Float);
       System.out.println ("V2 (float) = " + v2Float);
       System.out.println ("V1.V2 (float) = " + v1Float.dot(v2Float));
       System.out.println ("Angle (float)= " + (180.0*Math.acos(v1Float.dot(v2Float))/Math.PI));
       
       System.out.println ("");
       
       System.out.println ("V1 (double) = " + v1Double);
       System.out.println ("V2 (double) = " + v2Double);
       System.out.println ("V1.V2 (double) = " + v1Double.dot(v2Double));
       System.out.println ("Angle (double)= " + (180.0*Math.acos(v1Double.dot(v2Double))/Math.PI));



VectorDouble :
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
public class VectorDouble
   {
      public volatile double x;
      public volatile double y;
     
     
      public VectorDouble(double x,double y)
      {
         this.x=x;
         this.y=y;
      }
     
      public double length()
      {
         return Math.sqrt(x*x+y*y);
      }
     
      public VectorDouble normalize()
      {
         double length=this.length();
         x/=length;
         y/=length;
         return this;
      }
     
      public VectorDouble add(VectorDouble vector)
      {
         x+=vector.x;
         y+=vector.y;
         return this;
      }
     
      public VectorDouble mul(double k)
      {
         x*=k;
         y*=k;
         return this;
      }
     
      public double dot(VectorDouble vector)
      {
         return this.x*vector.x+this.y*vector.y;
      }
     
      public String toString()
      {
         return "(" + x + " : " + y + ")";
      }
   }



VectorFloat :
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
public class VectorFloat
   {
      public volatile float x;
      public volatile float y;
     
     
      public VectorFloat(float x,float y)
      {
         this.x=x;
         this.y=y;
      }
     
      public float length()
      {
         return (float)Math.sqrt(x*x+y*y);
      }
     
      public VectorFloat normalize()
      {
         float length=this.length();
         x/=length;
         y/=length;
         return this;
      }
     
      public VectorFloat add(VectorFloat vector)
      {
         x+=vector.x;
         y+=vector.y;
         return this;
      }
     
      public VectorFloat mul(float k)
      {
         x*=k;
         y*=k;
         return this;
      }
     
      public float dot(VectorFloat vector)
      {
         return this.x*vector.x+this.y*vector.y;
      }
     
      public String toString()
      {
         return "(" + x + " : " + y + ")";
      }
   }

Offline Roquen
« Reply #77 - Posted 2011-04-08 11:01:18 »

This is another bad & misleading example.
Offline dishmoth
« Reply #78 - Posted 2011-04-08 11:01:27 »

Does AffineTransform have the east facing as 0 degrees automatically?
An AffineTransform doesn't really decide those things.  My guess is that the 'default' direction for your game comes from the image you're loading in for your car sprite.  When you display that image unrotated, it seems reasonable to think of the direction it's facing as 'zero degrees' -- but that may go against the mathematical convention of zero degrees pointing east.

Quote
I'm at a loss as to why this isn't working out the way it's supposed to.
General tip:  Use System.out.println() (or your IDE's debugger) to print out the function's inputs and outputs.  (You could give your Vector2D class a print() or toString() method to help with this.)  Are the inputs what you'd expect?  Are the outputs what you'd expect given the inputs?  If you look closely enough you can work out exactly where things have gone wrong -- and then it's usually obvious what the problem is.

Simon

Offline Roquen
« Reply #79 - Posted 2011-04-08 11:10:25 »

WRT: signs flips will occur depending on a number of things.  The main one is the choice right vs. left coordinate systems.  Most "mathematical" reference assume a right handed coordinate frame (or coordinate system).
Offline jezek2
« Reply #80 - Posted 2011-04-08 11:14:40 »

V1 (float) = (0.6401844 : 0.7682213)
V2 (float) = (0.6401844 : 0.7682213)
V1.V2 (float) = 1.0000001
Angle (float)= NaN

V1 (double) = (0.6401843996644798 : 0.7682212795973759)
V2 (double) = (0.6401843996644798 : 0.7682212795973759)
V1.V2 (double) = 1.0
Angle (double)= 0.0

The same can happen for double with different values. You're just hiding a problem that needs to be solved. The correct way to do this would be to use atan2 which has guaranteed output range. Or clamp the input value for acos. Or refactor the code to not use angles at all (many things can be done in vectors/matrices/etc. alone).

Switching to double gives you false security that it's fixed but then it will *kaboom*. And it will be much worse to reproduce the bug as the precision error will get significant enough to trigger the bug after much more time than with floats.

One real example: I was using matrices for accumulating rotation (which is 'bad' thing) and the symptoms were pretty interesting: after some time one could notice the near clip plane slowly moved to far side... at first I thought it was something wrong in the projection matrix, but then realized it must come from some input matrices and found it. The solution was easy in my case, just renormalize it after applying incremental rotation to it. If I used doubles the bug would be triggered after longer time and would annoy players who play for few hours instead of 10mins or so and it would be much harder to reproduce for me.
Offline DzzD
« Reply #81 - Posted 2011-04-08 11:30:57 »

The same can happen for double with different values
inded,  same as capacity overflow can happen the same with int & short...

You're just hiding a problem that needs to be solved. The correct way to do this would be to use atan2 which has guaranteed output range. Or clamp the input value for acos. Or refactor the code to not use angles at all (many things can be done in vectors/matrices/etc. alone).

Switching to double gives you false security that it's fixed but then it will *kaboom*. And it will be much worse to reproduce the bug as the precision error will get significant enough to trigger the bug after much more time than with floats.

heu... I never said otherwise, nether said that double does not need error check too...

not really related but... another area where I often have problems related to float imprecision is when using 3D Studio Max... ( I know... I know... they should have used space partitioning eh ? Wink )

anyway you all won... I surrender... float are greaaaat ! float are fantastic ! float are magic !  Roll Eyes  Lips Sealed  Undecided

Offline jezek2
« Reply #82 - Posted 2011-04-08 12:04:53 »

inded,  same as capacity overflow can happen the same with int & short...

This is slightly different issue, integers have exact representation and the operations are also exact. So avoiding the overflow is much easier and more straightforward to think about.

not really related but... another area where I often have problems related to float imprecision is when using 3D Studio Max... ( I know... I know... they should have used space partitioning eh ? Wink )

Or 64bit fixed point as it has the same precision over the whole range.
Offline DzzD
« Reply #83 - Posted 2011-04-08 12:35:50 »

( sorry I come back... but something interresting I forgot to point is that ALL Math class method (like trigo function) use double as input, this include : atan2,cos,exp,tan,toDegree,toRadian etc... )

Offline Roquen
« Reply #84 - Posted 2011-04-08 12:37:05 »

anyway you all won... I surrender... float are greaaaat ! float are fantastic ! float are magic !  Roll Eyes  Lips Sealed  Undecided

Hehe. The point is if you don't know why you're using doubles instead of floats, you're doing yourself a disservice.  Unless you simply plan on using existing (hopefully correct) routines created by someone else.

For a chain of rotation compositions, use quaternions.  Much more stable and when errors start to compound, the normalization is easier.  (FWI: A non-unit quaternion acts as a rotation + a scale, where the scale factor is its magnitude squared).

(EDIT: Since it slowly creeps away from unity, you can do something like a single newton-ralphson step to push it back)
Offline DzzD
« Reply #85 - Posted 2011-04-08 12:41:19 »

Hehe. The point is if you don't know why you're using doubles instead of floats, you're doing yourself a disservice.  Unless you simply plan on using existing (hopefully correct) routines created by someone else.
or you dont know why you are using float...

I use double because :
 - I like precision
 - It run most of the time as fast as float
 - I cant see any reason to use float when you can use double

basically 90% of time for my project I use int for integer computation & double for floating computation

Offline jezek2
« Reply #86 - Posted 2011-04-08 13:10:45 »

( sorry I come back... but something interresting I forgot to point is that ALL Math class method (like trigo function) use double as input, this include : atan2,cos,exp,tan,toDegree,toRadian etc... )

Which is just limitation of Java API Smiley For example C math library has float versions. Also HotSpot seems to optimize eg. (float)Math.sqrt(floatArg) to float sqrt instead of using double version (don't remember where in HotSpot code it is, but this link should suffice as a proof). Dunno why they didn't just add float versions and instead did these workarounds.
Offline DzzD
« Reply #87 - Posted 2011-04-08 13:32:26 »

To be back ontopic, OP asked and I explain why I adviced to use double providing differents sample, feel free to explain why he should use float instead... Plz dont argue opengl. ..

Offline DzzD
« Reply #88 - Posted 2011-04-08 20:18:49 »

let do another test...

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
       double resultDouble = 0.0;
       float resultFloat = 0.0f;
       int resultInt =0;
       
       long startTime=System.currentTimeMillis();
          for(int n=1;n<100;n++)//nb: multiple call to get precise bench ...
            resultDouble = testSumDouble();
       long endTime=System.currentTimeMillis();
       
       long doubleTime=endTime-startTime;
         
       startTime=System.currentTimeMillis();  
          for(int n=1;n<100;n++)//nb: multiple call to get precise bench ...
            resultFloat = testSumFloat();
       endTime=System.currentTimeMillis();
       
       long floatTime=endTime-startTime;
       
       startTime=System.currentTimeMillis();  
          for(int n=1;n<100;n++)//nb: multiple call to get precise bench ...
            resultInt +=testSumInt();
       endTime=System.currentTimeMillis();
       
       long intTime=endTime-startTime;
       
       
       System.out.println("Test Double Sum" + resultDouble + " computed in " + doubleTime + "ms => global error " + 100*Math.abs(1000000/resultDouble-1.0) + "%");
       System.out.println("Test Float Sum= " + resultFloat + " computed in " + floatTime + "ms => global error " + 100*Math.abs(1000000/resultFloat-1.0) + "%");
       System.out.println("Exact result = 1000000");
       System.out.println("Test Int Sum= = " + resultInt + " need to print int result to avoid JIT optim and time "  + intTime + "ms for int test to show that it is not the loop that eat all the time...");
       System.out.println ("");


output :

Test Double Sum999999.9998389754 computed in 1342ms => global error 1.6102452704558345E-8%
Test Float Sum= 1087937.0 computed in 1326ms => global error 8.082914352416992%
Exact result = 1000000
Test Int Sum= = 990000000 need to print int result to avoid JIT optim and time 889ms for int test to show that it is not the loop that eat all the time...


Conclusion :

about precision :  
   float error : about 8%
   double error : less than 0.000...1%

about speed :
    global difference : about 16ms => can be considered as not significant

so... yes, I still generaly prefer to use double, (need to mention that float implies a lot of cast too and the use of "f" suffix...), and really I definitly know why I prefer using double Wink


I ve worked with float for long time in C/C++ (before going with java) and at that time I got good reason to do such but nowadays and with java double are better (wich is not yet the case between long and int)... my idea is that most people use float without really knowing why, and mostly because they have seen one doing such and than without looking further....

Offline jezek2
« Reply #89 - Posted 2011-04-08 22:53:49 »

Test Double Sum999999.9998389754 computed in 1342ms => global error 1.6102452704558345E-8%
Test Float Sum= 1087937.0 computed in 1326ms => global error 8.082914352416992%
Exact result = 1000000

Everyone knows accumulation is one of worst cases so double for the temporary variable is the way to go in most cases unless the performance (eg. by using vectorized SSE2 code) is much more important. Otherwise floats are sufficient for most use cases. Takes half the memory, no need for conversions when passing into OpenGL and you can process 4x float at once with SSE2 instead of just 2xdouble (though not relevant for pure Java).

The argument about preferring it because of Java's deficiencies in API and the way number literals works in Java (and which is just about being used to one particular style) is quite ridiculous. If you don't like the casts you can fix the API by creating bunch of static methods that takes float as well.

I ve worked with float for long time in C/C++ (before going with java) and at that time I got good reason to do such but nowadays and with java double are better (wich is not yet the case between long and int)... my idea is that most people use float without really knowing why, and mostly because they have seen one doing such and than without looking further....

Which you're exactly doing, using double for everything without knowing why. In many cases it's just wasteful. It's like using long for everything instead of int. Sure matters little less on 64bit, but in some applications the twice size of pointers is quite significant overhead in memory.

And for example HotSpot has ability to use shifted 32bit pointers in 64bit mode so they can access 32GB of heap memory at maximum which is ok limit for most usages and takes less memory.
Pages: 1 2 [3] 4 5
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

xsi3rr4x (53 views)
2014-04-15 18:08:23

BurntPizza (51 views)
2014-04-15 03:46:01

UprightPath (65 views)
2014-04-14 17:39:50

UprightPath (48 views)
2014-04-14 17:35:47

Porlus (65 views)
2014-04-14 15:48:38

tom_mai78101 (89 views)
2014-04-10 04:04:31

BurntPizza (149 views)
2014-04-08 23:06:04

tom_mai78101 (245 views)
2014-04-05 13:34:39

trollwarrior1 (203 views)
2014-04-04 12:06:45

CJLetsGame (210 views)
2014-04-01 02:16:10
List of Learning Resources
by SHC
2014-04-18 03:17:39

List of Learning Resources
by Longarmx
2014-04-08 03:14:44

Good Examples
by matheus23
2014-04-05 13:51:37

Good Examples
by Grunnt
2014-04-03 15:48:46

Good Examples
by Grunnt
2014-04-03 15:48:37

Good Examples
by matheus23
2014-04-01 18:40:51

Good Examples
by matheus23
2014-04-01 18:40:34

Anonymous/Local/Inner class gotchas
by Roquen
2014-03-11 15:22:30
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!