Jump to content
  • Advertisement
Sign in to follow this  
Neometron

Floats and Android Devices

This topic is 1773 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello everyone,

Last week I encountered a particular situation dealing with floats in my Android project.  I have two devices, a tablet and a cell phone, that give different results after computations. There is a continuous collision system for a ball and it falls with gravity.  It works perfectly on the tablet device, but on the phone the ball falls through the table. After stepping through the code, the only difference found between devices were the time of impact  ~0.04/s. This caused the ball to be embedded with the surface and falls through.

So in general, what is the difference between accuracy and precision?  Is the terms accuracy and precision one and the same? I know floats don't have that great of precision, but with margin of errors in the hundredth's place?


 

Share this post


Link to post
Share on other sites
Advertisement

In general a float has six decimal digits of precision.

 

That error propagates and accumulates with each operation.  That is partially why it is important to keep a single canonical source of numbers and numbers based on get get recomputed.  

 

Exactly how it accumulates and propagates depends entirely on your program, your algorithms, even your compiler options.

 

 

 

A simple example of error accumulation and propagation:  float sum = 0; for(i=0; i<10000; i++) sum += 0.0001;  The end result is theoretically 1.0 if you were doing paper math, but with finite numbers in floating point the result is not quite what you expect.  Even though each individual number has six decimal digits of precision, by the time you have summed the result 10000 times the error accumulates to something significant.

 

So really it is important to detail HOW you are using the floating point numbers.  If your code allows error to accumulate and propagate issues like you described can occur.  If your code limits error accumulation and propagation you can get expected results on all platforms and devices.

Edited by frob

Share this post


Link to post
Share on other sites
One thing to look out for is your numerical integration algorithms, in particular for integration of position and velocity. A lot of people when creating their physics simulation use naive formulas that look like:
v = v + a * dt
x = x + v * dt
Unfortunately, this naive version accumulates errors rapidly. Even a simple midpoint integration algorithm accumulates error much more slowly
vf = v + a * dt
x = x +(v + vf) * dt / 2
v = vf

Share this post


Link to post
Share on other sites

Very interesting;
Running
 float sum = 0; for(i=0; i<10000; i++) sum += 0.0001; yields 1.0000535 where doubles are 0.9999999999999062.

So currently there could be a potential problem even on my tablet over a span of time. I do check some results against an epsilon value of 0.001, but does this have to be done on every operation? How would one combat error accumulation? Is switching to doubles the answer or is that kicking the can down the road? Do I have to round all results before continuing?

Questions seem to result in more questions ;)

Share this post


Link to post
Share on other sites

SiCrane,
My physics is essentially the same from you have shown.

This worries me that over time values will have so many errors that it will break the game.

Share this post


Link to post
Share on other sites

The point of both of those is that floating point values, either float type or double type, will accumulate errors.  The quick little 10000 item sample is a very easy way to demonstrate it.  It shows that as you accumulate error it grows over time.

 

Switching to doubles gives you more digits of precision but the error will still accumulate and propagate.

 

 

You need to be aware of the issue and code accordingly. Always remember that floating point numbers (both float and double) are approximations.  

 

 

 

As a consequence of that, you should not compare against an exact number but against a range. You cannot easily test for a precise collision, but instead test for an intersection along a line between before/after positions. 

 

For physics and other animations it is often wise (although not always possible) to compute key points directly rather than through accumulation. Like the midpoint algorithm shown above, with physics algorithms it is possible to know the actual position based on the parameters rather than accumulating values over time.  You can recompute the actual values and use those directly rather than accumulating a small bit of error every update.  There will still be a tiny bit of error but it will not accumulate.

Share this post


Link to post
Share on other sites

SiCrane,
My physics is essentially the same from you have shown.

This worries me that over time values will have so many errors that it will break the game.

You should probably look into using a fixed time step then, then all devices will produce the same integration errors.

Share this post


Link to post
Share on other sites

Thanks Hodgman for the article. I have seen fixed time step method used in the Minecraft server code when I created mods for my home server. However, I have not used this method in my current project. Although, while debugging, I have set my time delta to 1.0 to check consistency between devices.

It turns out this was causing different values:

double mag = Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2) + Math.pow(this.z, 2));

 

I have changed it to this and everything became consistent and my ball collides on both devices: 

double mag = Math.sqrt((this.x*this.x) + (this.y*this.y) + (this.z*this.z));

 

Why is this?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!