Rounding error, very common when dealing with angles.

https://www.scirra.com/blog/141/common- ... nd-gotchas

[quote:127woonl]Expecting math calculations to be exact

All modern computers store fractional numbers like 0.5 in a floating point format. If you want to learn more about it feel free to follow up the link, but we won't be detailing it here. The main point is because computers don't have infinite processing power and memory, they must sometimes slightly round results. This in turn can cause the result of a calculation to be slightly off its true mathematical answer, such as getting 0.999999 when you expected 1.

To illustrate why this happens, consider dividing 1 by 3 with limited precision. The answer is of course 0.333333333... recurring forever. However computers have a limited amount of memory and can't possibly store an infinitely recurring number like that in full. Therefore they reserve room for a fixed number of digits, then stop. For example it might calculate with six digits and come up with the answer 0.333333. This is mathematically wrong, but your computer cannot possibly store the "right" answer, so it has to make do. Then suppose you multiply this result by 3 again. You'd expect three thirds to equal 1, but in fact you get 0.999999 - close to the right answer, but not exact. If your game expected the answer to exactly equal 1, you might find it's not working like you expected. You can usually inspect your project with the debugger to see the real answer that was calculated.

This type of error affects all floating-point calculations in almost all software in all modern processors. There's no escape! It's just a fact of how computers work. The real details are slightly different - my example used decimal (base 10) whereas the actual representation is in binary (base 2), and recurring decimals work differently in base 2. For example the number 0.1 is exact in base 10, but is a recurring decimal in base 2. This means rounding can happen in unexpected places, even if you think you're dealing with exact numbers. It's particularly likely to affect object positions, since moving an object at an angle involves calculating sin and cos, which will usually produce results close to but not exactly the true answer.

The workaround, which you must use with any software and any framework, is to allow a small tolerance. Don't expect an event like "Sprite X = 100" to ever be true. Instead use something like abs(Sprite.X - 100) < 0.01. This allows the comparison to be true so long as the result is within 0.01 of 100, so if it works out to 99.999999 your event still runs as expected.