Jump to content

  • Log In with Google      Sign In   
  • Create Account

Floats and Android Devices


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
10 replies to this topic

#1 Neometron   Members   -  Reputation: 364

Like
0Likes
Like

Posted 05 August 2013 - 09:00 AM

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?


 



Sponsor:

#2 frob   Moderators   -  Reputation: 21072

Like
3Likes
Like

Posted 05 August 2013 - 09:51 AM

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, 05 August 2013 - 09:55 AM.

Check out my personal indie blog at bryanwagstaff.com.

#3 SiCrane   Moderators   -  Reputation: 9593

Like
3Likes
Like

Posted 05 August 2013 - 10:34 AM

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


#4 Neometron   Members   -  Reputation: 364

Like
0Likes
Like

Posted 05 August 2013 - 10:57 AM

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 ;)



#5 Neometron   Members   -  Reputation: 364

Like
0Likes
Like

Posted 05 August 2013 - 11:05 AM

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.



#6 frob   Moderators   -  Reputation: 21072

Like
2Likes
Like

Posted 05 August 2013 - 01:20 PM

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.


Check out my personal indie blog at bryanwagstaff.com.

#7 DT....   Members   -  Reputation: 487

Like
-1Likes
Like

Posted 07 August 2013 - 02:00 AM

http://gafferongames.com/networking-for-game-programmers/floating-point-determinism/


Edited by DonTzzy, 09 September 2013 - 12:47 AM.


#8 DT....   Members   -  Reputation: 487

Like
0Likes
Like

Posted 09 August 2013 - 04:02 AM

.


Edited by DonTzzy, 11 August 2013 - 07:21 AM.


#9 Hodgman   Moderators   -  Reputation: 30341

Like
1Likes
Like

Posted 09 August 2013 - 06:17 AM

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.



#10 Neometron   Members   -  Reputation: 364

Like
0Likes
Like

Posted 13 August 2013 - 08:13 AM

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?



#11 Hodgman   Moderators   -  Reputation: 30341

Like
0Likes
Like

Posted 13 August 2013 - 08:52 AM

Short answer: "because float"

Long answer: http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

Medium answer:

Floating point math is deterministic, in that the same operations on the same data will always produce the same results...

...but slightly different operations that should be mathematically equivalent, may produce slightly different rounding errors.

 

It's possible that one of your implementations of Java has a different implementation of the pow function than the other. Because you're using Java, you're at the mercy of the device's JVM in which floating point instructions it uses. Without being able to control the FP instructions yourself, it's likely that you won't be able to achieve 100% determinism across different platforms.


Edited by Hodgman, 13 August 2013 - 08:53 AM.





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS