One thing to be careful about when programming games is relying on the rules of algebra. Simple laws like the Associative Law and Distributive Law don't always work when using floating point numbers. I'll give some Python code to demonstrate, but these problems are with floats, not with Python.
- Distributive Law. We've been taught that a * (b + c) == (a * b) + (a * c).
a, b, c = 0.111, 0.201, 0.305 s1 = a * (b + c) s2 = (a * b) + (a * c) print '%.08f - %.08f = %.08f' % (s1, s2, s1 - s2) print ' equal? %s' % (s1 == s2)
These are the results:
0.05616600 - 0.05616600 = -0.00000000 equal? False
The difference looks like 0, but it's not. The two sums are not equal. To see the problem, change the format specifier
- Associative Law. We've been taught that a + (b + c) == (a + b) + c. When some of those are negative and some are positive (and occasionally even when they're all positive), the results won't be the same.
- Additive Inverse. We've been taught that a + b - b == a.
a = 1e-30 b = 1e+30 print a, a + b - b, (a + b - b) == a
The result is that (a + b - b) != a. You can look at this example as a special case of the Associative Law.
To some of you these problems will seem obvious and not a big deal for most applications. Why do I bring it up in this blog? Loss of precision can open up exploits in multiplayer games. Let's consider a game in which you can trade with someone else, and the total amount of money is represented as a float. If player A has a large amount of money a, he may be able to send a very small amount x to B (who has b) without it affecting his own amount. We can have a + b < (a - x) + (b + x), which means this exploit creates new money out of nowhere.
If you're using floating point numbers, be sure to use double precision. Alternatively, use integers or fixed point arithmetic to avoid some of these issues. If you do a lot of math in your game, be sure to learn about numerical programming. There are a lot more issues than the simple ones I describe here.