Fixed-point

From OdaWiki
Revision as of 16:32, 11 August 2012 by AlexMax (Talk | contribs) (Created page with "Doom was created when floating-point operations were considered expensive. Thus, it uses a <code>fixed_t</code> when dealing with numbers with fractional parts. A <code>fixe...")

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Doom was created when floating-point operations were considered expensive. Thus, it uses a fixed_t when dealing with numbers with fractional parts. A fixed_t is actually just a normal 32-bit int, but using the fixed_t type more clearly signifies intent.

Conversion

So how do you represent a fraction with a type that is designed for storing whole numbers? You simply use the first 16 bits for representing the whole part of the number, and the other 16 bits for representing the fraction. Thus, to convert an integer to a fixed-point representation, you simply shift left by 16. Doom has a handy constant for this called FRACBITS, so it ends up looking like fixed_number << FRACBITS. If you want to get the whole number out of the fixed_t value, you simply shift right by 16 (fixed_number >> FRACBITS). If you want the fractional part out of the fixed_t for some reason, you simply mask it out by doing a logical AND against the first four bits (fixed_num & 0xFFFF).

Of course, sometimes you have a floating point number that you need to convert to a fixed_t and vice-versa. Doom has two handy macros for converting back and forth, FLOAT2FIXED and FIXED2FLOAT. If you need the number 1 in a fixed-point representation, you don't need to derive it yourself. Doom already has the number 1 as a fixed-point constant, FRACUNIT.

Arithmatic

Before you proceed, a word of warning. Fixed-point arithmetic only has 16-points of whole number precision (−32,768 to 32,767), so it is much easier to overflow than a normal numeric or floating point type. If you need bigger numbers, you're likely better off using something else.

To add or subtract two fixed-point numbers, simply use a normal addition or subtraction operator.

Multiplication is a little tricky. If you want to multiply a fixed-point number by an integer, simply use a normal multiplication operator. However, if you want to multiply or divide two fixed-point numbers, Doom has two purpose-built functions for that purpose: FixedMul and FixedDiv. Both of these are very easy to overflow, so be careful.