Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I am working on a cross-platform multiplayer RTS game where the different clients and a server(flash and C#), all need to stay deterministically synchronised.

To deal with Floatpoint inconsistencies, I've come across this method: http://joshblog.net/2007/01/30/flash-floating-point-number-errors/#comment-49912 which basically truncates off the nondeterministic part:

return Math.round(1000 * float) / 1000;

Howewer my concern is that every time there is a division, there is further chance of creating additional floatpoint errors, in essence making it worse?

.

So it occured to me, how about something like this:

function floatSafe(number:Number) : Number 
{return Math.round(float* 1024) / 1024; }
  • ie dividing with only powers of 2 ? What do you think?

.

Ironically with the above method I got less accurate results:

trace(  floatSafe(3/5) ) // 0.599609375 

where as with the other method(dividing with 1000), or just tracing the raw value I am getting 3/5 = 0.6

or Maybe thats what 3/5 actually is, IE 0.6 cannot really be represented with a floatpoint datatype, and would be more consistent across different platforms?

share|improve this question
add comment

2 Answers 2

up vote 2 down vote accepted

Floating point isn't "non-deterministic". There's no randomness. The floating point value of 1/10 will always be greater than the actual value of 1/10, not just some of the time. The rules are predictable - it's just sometimes hard to know which rules it is using.

Anyway, rounding the value is not guaranteed to work, even if accumulated error wasn't a problem. Any individual error introduced (where error can be defined as a result different from a hypothetical baseline) could make the difference between a value rounding up or a value rounding down, so the rounding operation itself could produce different results on different machines. So basically you eliminate something like 99.9% of your inaccuracies in exchange for getting a much larger inaccuracy 0.1% of the time.

A better idea is to use something truly deterministic, such as fixed point arithmetic, or to set the processor's floating point rules (which may not be possible on your platform).

share|improve this answer
    
There would not be any accumulated errors, as the game is built on all integer maths. However in some very rare instances a Float is required, and in those cases I would like to 'sanitize' those floats as much as possible. so wouldn't the division by 1024 solve this problem? as that is on the power of 2, which I hope would make it consistent how the different platforms(C# and Flash) and different computers perform that operation? –  Martin K Jul 6 '12 at 22:27
1  
Either you are exchanging data based on floats or you're not - if you are not, it's completely safe and you don't have to sanitise anything. If you are, it's completely unsafe and the fact that most of it is done with integers doesn't help. It doesn't matter what you round with or to - the wrong information is already in the value and multiplying it makes it worse. –  Kylotan Jul 6 '12 at 22:38
1  
That logic assumes that all errors are positive biases. What happens if you truncate 0.99999999999999 and 1.0000000000000? –  Kylotan Jul 6 '12 at 23:43
1  
What "rare instances" require floating point numbers? If we can design around those instances then your original problem is solved, and without trickery. –  Patrick Hughes Jul 6 '12 at 23:46
1  
The point is that rounding does not solve your problem, even if you do it by a number that doesn't introduce extra error. Any rounding (or truncation/flooring) operation has 2 adjacent values where one will round up and one will round down. And if your error is large enough so that a number falls on the wrong side of that threshold, no operation can fix it as the information is already lost. The problem needs fixing before you get to this point. –  Kylotan Jul 7 '12 at 3:03
show 12 more comments

A value like 0.99900000000000000001 is there because the float cannot represent the original number at all not because the actual operation wasn't correct.

http://steve.hollasch.net/cgindex/coding/ieeefloat.html

That is a the IEEE standard just to give you a reason why rounding wont work. This doesn't mean all CPUs use this format.

I think people serialize their floating point numbers to a standard format over wire and remake the float on the other end, but I'm not entirely sure. You could try doing something like LISP programming langauge and find the value as a "x/y" then send x and y to the client and have him perform "x/y" to get the float.

share|improve this answer
    
Thank you for your answer, and I am aware of that, however as the OP explained, a consistency required which is cross platform ( Flash/C# )and cross system ( PC/Mac/Server). The solution is to use a float which is altogether less precise, IE only have 3-4 decimals. And my question concerned is that if by the act of rounding to 3 decimals, am I exposing myself to extra errors when I divide by 1000, and if it would be better to divide by 1024 ( as that is the powers of 2 ) –  Martin K Jul 7 '12 at 10:36
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.