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'm reading a fantastic article about game timer precision and here is a quote about 2/3 of the way into the article:

If you start your game clock at about 4 billion (more precisely 2^32, or any large power of two) then your exponent, and hence your precision, will remain constant for the next ~4 billion seconds, or ~136 years.

He doesn't give a concrete example of this though. Does this mean I would want to add 2^32 to the game clock value that I store at the beginning of each frame? Or is there a way to actually set the clock in Windows so that the numbers start at 2^32?

share|improve this question

4 Answers 4

up vote 11 down vote accepted

TL;DR The author is not suggesting you implement this in your game. He's telling you that the precision will be slow changing, but bad.

This means the float you're using to track your game time would start at 2^32. Because setting the number that large to start with, whatever you add on to it in the next 136 years, won't change the exponent.

Though, the precision will remain constant, it doesn't mean it's better. The precision gets worse the larger the number. Starting with a large number just means that the precision won't change over the life of the counter, but the precision is worse than starting with a small number. If you started at 0 the exponent would change frequently at first, meaning the precision changes frequently.

Concrete example:

float twoToThirtyTwo = 4294967296;
float game_time_elapsed = twoToThirtyTwo;

float getTimeElapsed() {
     return game_time_elapsed - twoToThirtyTwo;
 }

I believe overall the article is suggesting using floats for time deltas (short/small time spans) and using ints or longs for time elapsed (long/large time spans).


The author suggests a change to the code above to make it usable, since it's currently an example of how you can have constant bad precision. Change to a double:

double twoToThirtyTwo = 4294967296;
double game_time_elapsed = twoToThirtyTwo;

double getTimeElapsed() {
     return game_time_elapsed - twoToThirtyTwo;
 }

That code should give a constant good precision (around 1 microsecond) for a long time.

share|improve this answer
2  
Im a fan of storing the times instead in big integers and converting the elapsed delta times to a float for calculations.. works nice i'd say ;D –  Grimshaw Sep 18 '12 at 0:18
    
ah, now I get what he's saying. The precision for numbers from 2^32 to 2^33 is the same, so we have the same precision for 2^32 seconds. thanks for the different perspective. –  Philip Sep 18 '12 at 18:48
1  
The code above will fail miserably because it is using 'float' for game_time_elapsed. At that range the precision of a float is 256 s -- the next time that can be represented is 2^32+256. That's why I recommended two things: 1) Use a double so you have enough precision when the game has been running for a while. 2) Start at 2^32 so that the precision is consistent. The other reason to use 2^32 is so that you will instantly hit precision problems if you store elapsed game time in a float. –  Bruce Dawson Sep 23 '12 at 20:42
    
@BruceDawson Indeed, it wasn't meant to be used, only to show a concrete example of what I thought you were saying in your article, i.e. don't do it that way. It was made before you edited your article to be more clear. Suitable changes? –  Byte56 Sep 23 '12 at 20:46

Most games have a function that calculates the current time -- perhaps using QueryPerformanceCounter(), perhaps using GetTickCount64(), perhaps using something else. Normally this function is designed so that it initially returns zero, and then gradually returns larger numbers.

What the author is saying (and I can be definitive about this because I am the author) is:

  • The first value returned should be 2^32 instead of zero and it should smoothly increment from there.
  • The return value should be a double, not a float.
  • Comments on the article itself instead of here would be better.
share|improve this answer
    
Bruce, thanks for making an answer! Though I can't really agree with your last point :), you make things clearer. So you do recommend implementing this. The reasoning being that having a constant precision, even though it's not as good as it can be, is better than having better precision that's changing? –  Byte56 Sep 19 '12 at 13:16
    
Exactly. Having precision that varies over time is horrible. –  Bruce Dawson Sep 20 '12 at 6:11
    
Tom Forsyth and I debate whether it is better to use 64-bit fixed point or 64-bit doubles. I find the convenience of doubles significant for games because everything we do with time is floating-point calculations. If it's going to be floating-point, let's go straight there. I would say, what advantage is there to using fixed-point? Double can have consistent precision, plenty of precision, and is not error-prone with an appropriate start point. I don't think that developer convenience is irrelevant. Double allows natural units, instead of unwieldy large numbers. –  Bruce Dawson Sep 20 '12 at 6:14

Here's another discussion on game timer implementation and accuracy, complete with source code, that may help you with your game timer requirements.

Cygnon's Blog: Game Programming Adventures

share|improve this answer
    
In case that link goes dead: the poster suggests using Bresenham's line algorithm, with the (high-frequency) system clock as the x axis and the (low-frequency) game clock as the y axis. –  David Moles Jun 15 at 15:37

From Tom Forsythe's article (which is linked from Bruce's article, but not really discussed:

One "solution" [to floating point precision problems] is to turn on double precision, because then you get more bits. Yeah, but you've just shuffled the problem around. Doubles have exactly the same weaknesses [as floats] - all you've done is shuffle the problems into a corner, stuck your fingers in your ears and yelled "lalalalalala". They'll still come back to bite you, and because it's double precision, it'll be even rarer and even harder to track down. And they're slower on most machines, so you've hurt your execution speed.

(my clarifications in bold)

Precision problems make floats and doubles just a fundamentally bad choice for representing absolute time. This is why Windows doesn't use them to represent absolute time. This is why OS X doesn't use them to represent absolute time. This is why Linux, BSD, Solaris, and every other OS under the sun doesn't use them to represent absolute time.

If you're storing the absolute game time, you really are better off using fixed point integers. Reliable, repeatable, and with consistent precision across their whole range. "Because I like seconds" is a pretty feeble reason to move to imprecise and error-prone storage for something as critical to a game as its internal clock, if you ask me.

share|improve this answer
    
Agreed. Before his article was edited it seemed that it could go either way. I was surprised that the author promoted the use of floating point, especially with large numbers. Perhaps if he comes back he can answer the "why?" part of the answer. –  Byte56 Sep 20 '12 at 4:48
1  
At the recommended range (2^32 and beyond) a double has nanosecond precision, which I would hardly call imprecise. I'm also not clear as to what is "error-prone" about a double. I would claim that by using natural units it is less error prone than, for instance, the 100 ns units of some Windows timers. What is imprecise and error-prone about my suggestion? –  Bruce Dawson Sep 23 '12 at 20:45
1  
timeA - timeB + timeB == timeA (and similar simple algebraic operations). Works with integers. Not guaranteed with floats or doubles, just because of the way that floating point numbers work on computers. –  Trevor Powell Sep 23 '12 at 22:29

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.