Sign in to follow this  
codingsolo

.01f != 0.0099999998 !!!!!!!!!!

Recommended Posts

I am setting a float to 0.01f but it immediately gets the value of 0.009999999998! Any insight on the loss of precision of something that only has a hundredth of a decimal place? Brandon

Share this post


Link to post
Share on other sites
Floating point numbers are not exact. The float datatype in C and C++ has about 7 significant digits meaning that 0.01f could also be equal to any value in the interval (0.009999998, 0.01000001). This is what you're seeing.

Share this post


Link to post
Share on other sites
Quote:


The IEEE standard goes further than just requiring the use of a guard digit. It gives an algorithm for addition, subtraction, multiplication, division and square root, and requires that implementations produce the same result as that algorithm. Thus, when a program is moved from one machine to another, the results of the basic operations will be the same in every bit if both machines support the IEEE standard. This greatly simplifies the porting of programs. Other uses of this precise specification are given in Exactly Rounded Operations.


Reading this leads me to believe that using floating point *is* safe for networked games that must be in sync each frame. Am I wrong here?

Share this post


Link to post
Share on other sites
Quote:
Original post by Daniel Miller
Quote:


The IEEE standard goes further than just requiring the use of a guard digit. It gives an algorithm for addition, subtraction, multiplication, division and square root, and requires that implementations produce the same result as that algorithm. Thus, when a program is moved from one machine to another, the results of the basic operations will be the same in every bit if both machines support the IEEE standard. This greatly simplifies the porting of programs. Other uses of this precise specification are given in Exactly Rounded Operations.


Reading this leads me to believe that using floating point *is* safe for networked games that must be in sync each frame. Am I wrong here?

Yes, I've mentioned this in my most recent journal posting, but if you were to have one of your clients using SSE instruction sets, and another using the FPU, you can easily obtain results that differ in the least significant digits. This is due to a difference in the size of the registers used to calculate the numbers (32 bit float is widened to 80 bit on FPU, while it remains at 32 in the XMM registers).

Share this post


Link to post
Share on other sites
Quote:
Original post by Washu
Quote:
Original post by Daniel Miller
Quote:


The IEEE standard goes further than just requiring the use of a guard digit. It gives an algorithm for addition, subtraction, multiplication, division and square root, and requires that implementations produce the same result as that algorithm. Thus, when a program is moved from one machine to another, the results of the basic operations will be the same in every bit if both machines support the IEEE standard. This greatly simplifies the porting of programs. Other uses of this precise specification are given in Exactly Rounded Operations.


Reading this leads me to believe that using floating point *is* safe for networked games that must be in sync each frame. Am I wrong here?

Yes, I've mentioned this in my most recent journal posting, but if you were to have one of your clients using SSE instruction sets, and another using the FPU, you can easily obtain results that differ in the least significant digits. This is due to a difference in the size of the registers used to calculate the numbers (32 bit float is widened to 80 bit on FPU, while it remains at 32 in the XMM registers).


Since I'm a noob and have no idea how to do that, would that happen by itself? Or do I have to explicitly use SSE?

Share this post


Link to post
Share on other sites
Quote:
Original post by Daniel Miller
Quote:
Original post by Washu
Yes, I've mentioned this in my most recent journal posting, but if you were to have one of your clients using SSE instruction sets, and another using the FPU, you can easily obtain results that differ in the least significant digits. This is due to a difference in the size of the registers used to calculate the numbers (32 bit float is widened to 80 bit on FPU, while it remains at 32 in the XMM registers).


Since I'm a noob and have no idea how to do that, would that happen by itself? Or do I have to explicitly use SSE?

If you enable SIMD instruction sets, it can happen by itself. One common case where you might find this happening would be an optimized math library that changes its behavior based on the instruction sets available on the client PC.

Share this post


Link to post
Share on other sites
Quote:
Original post by Washu
Quote:
Original post by Daniel Miller
Quote:
Original post by Washu
Yes, I've mentioned this in my most recent journal posting, but if you were to have one of your clients using SSE instruction sets, and another using the FPU, you can easily obtain results that differ in the least significant digits. This is due to a difference in the size of the registers used to calculate the numbers (32 bit float is widened to 80 bit on FPU, while it remains at 32 in the XMM registers).


Since I'm a noob and have no idea how to do that, would that happen by itself? Or do I have to explicitly use SSE?

If you enable SIMD instruction sets, it can happen by itself. One common case where you might find this happening would be an optimized math library that changes its behavior based on the instruction sets available on the client PC.


I am using DirectX/C#. Would that happen by itself (I wouldn't be using any 3D math, this is a 2D game)? Thanks a bunch for your insight.

EDIT: punctuation
EDIT: spelling 'punctuation'

Share this post


Link to post
Share on other sites
Quote:
Original post by Daniel Miller
Quote:
Original post by Washu
Quote:
Original post by Daniel Miller
Quote:
Original post by Washu
Yes, I've mentioned this in my most recent journal posting, but if you were to have one of your clients using SSE instruction sets, and another using the FPU, you can easily obtain results that differ in the least significant digits. This is due to a difference in the size of the registers used to calculate the numbers (32 bit float is widened to 80 bit on FPU, while it remains at 32 in the XMM registers).


Since I'm a noob and have no idea how to do that, would that happen by itself? Or do I have to explicitly use SSE?

If you enable SIMD instruction sets, it can happen by itself. One common case where you might find this happening would be an optimized math library that changes its behavior based on the instruction sets available on the client PC.


I am using DirectX/C#. Would that happen by itself (I wouldn't be using any 3D math, this is a 2D game). Thanks a bunch for your insight.

Assuming you are using XNA/MDX, then no. It's 32 bit only and will use just the FPU. A more portable MDX library would allow for 64 bit and 32 bit executables, in that case you could encounter it since the .NET x64 platform does use SSE2 for the majority of its floating point operations.

Share this post


Link to post
Share on other sites
Quote:
Original post by Daniel Miller
If you need to keep two clients in sync without a central server, is fixed point the only option?


No. There's no problem with using floats, as long as you don't make assumptions that require them to be exactly perfect to X decimal places.

Does it matter if one client thinks an object is 0.0000003 metres to the left of where it actually is? If the answer to this question is "yes", then you should probably re-think your network design.

Share this post


Link to post
Share on other sites
Quote:
Original post by Hodgman
Quote:
Original post by Daniel Miller
If you need to keep two clients in sync without a central server, is fixed point the only option?


No. There's no problem with using floats, as long as you don't make assumptions that require them to be exactly perfect to X decimal places. Does it matter if one client thinks an object is 0.0000003 metres to the left of where it actually is?


Very much so, if that causes a shot to become out of range so a unit doesn't die. That unit might kill a third unit, which would have killed a fourth unit, etc. In a RTS, things could spiral out of hand quickly.

Share this post


Link to post
Share on other sites
Quote:
Original post by Daniel Miller
Quote:
Original post by Hodgman
Quote:
Original post by Daniel Miller
If you need to keep two clients in sync without a central server, is fixed point the only option?


No. There's no problem with using floats, as long as you don't make assumptions that require them to be exactly perfect to X decimal places. Does it matter if one client thinks an object is 0.0000003 metres to the left of where it actually is?


Very much so, if that causes a shot to become out of range so a unit doesn't die. That unit might kill a third unit, which would have killed a fourth unit, etc. In a RTS, things could spiral out of hand quickly.


That should all be computed on the server, which would know the true values (since the server should be in charge of those values, not the client).

Share this post


Link to post
Share on other sites
Floating-point values mean fuzzy-equality, you have to use an epsilon value to determine if the the numbers are "close-enough" to be considered equal.

//integer logic
if (x==y)

//floating-point logic
static const float epsilon = 1e-5
if abs(y-x) < epsilon

I don't recall the most efficient way to code it, but that's the logic to it.

Share this post


Link to post
Share on other sites
Read also this:
http://realtimecollisiondetection.net/pubs/GDC06_Ericson_Physics_Tutorial_Numerical_Robustness.ppt

talks about how to define the epsilon based on the numbers that are compated

Share this post


Link to post
Share on other sites
there are networked games that use determinism and lock-steps to reduce bandwidth. It's also a great anti-hack, since everyone will share the same deterministic state, you can verify data checksums and make sure everyone's in sync.

So really, there is a case for having all players share the same FPU precision and making sure they achieve the same result. And the innacuracies you see with floating point will not matter when that is the case, they will all share the same innacuracies, but they will remain in sync, they'll all be 'wrong; equally.

Share this post


Link to post
Share on other sites
Quote:
Original post by Washu
Quote:
Original post by Daniel Miller
Quote:
Original post by Hodgman
Quote:
Original post by Daniel Miller
If you need to keep two clients in sync without a central server, is fixed point the only option?


No. There's no problem with using floats, as long as you don't make assumptions that require them to be exactly perfect to X decimal places. Does it matter if one client thinks an object is 0.0000003 metres to the left of where it actually is?


Very much so, if that causes a shot to become out of range so a unit doesn't die. That unit might kill a third unit, which would have killed a fourth unit, etc. In a RTS, things could spiral out of hand quickly.


That should all be computed on the server, which would know the true values (since the server should be in charge of those values, not the client).


RTS games don't have a central server that deal with that information, each game runs in parallel on all players' computers.

Share this post


Link to post
Share on other sites
Quote:
Original post by Daniel Miller
Quote:
Original post by Washu
That should all be computed on the server, which would know the true values (since the server should be in charge of those values, not the client).


RTS games don't have a central server that deal with that information, each game runs in parallel on all players' computers.

No. That's simply a design decision that was opted to be made by most RTS games, it is not a requirement at all. Never the less, the issue isn't nearly as bad as you think, since you should be using deltas for comparison. Thus even if the unit thought it was 0.0000003 off from where it really was, the delta would more than make up for that.

As for the OP: Some numbers cannot be represented in base 2 systems, just like some numbers cannot be represented in base 10 systems. 1/3 is a prime example of a number that cannot be represented exactly in a finite decimal notation. (note that when you extend this to an infinite number of digits you find that you can represent any rational number in either system).

Share this post


Link to post
Share on other sites
I would wager that even RTS games give server authority over hits and deaths. Most it probably wouldn't matter, but a game like Supreme Commander that simulates every shot it probably does.

Share this post


Link to post
Share on other sites
Quote:
Original post by DrEvil
I would wager that even RTS games give server authority over hits and deaths. Most it probably wouldn't matter, but a game like Supreme Commander that simulates every shot it probably does.


Because there are so many units, having a central "server" that deals with logic would be too expensive. Supreme Commander uses the same approach as all other RTS games.

Washu: I would think that even if you use an epsilon, the discrepancy could (after a long game) cause everything to de-sync. Plus, if something lies on the "edge" of the epsilon, it could de-sync rather quickly. You are obviously a more knowledgeable programmer than I am, so am I wrong here?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this