fixed point math - the fraction component question.

Started by
7 comments, last by bakery2k1 18 years ago
the format im using for my conceptual experiments with fixed point math is 16:16 (16 bits for the whole number and 16 bits for the fractional number). so if i were to represent 1.5f in fixed point, how do i do it? So far i've come up with the following concept: var = 1; var = var << 16; that takes care of the integer component. but how do i take care of the fractional .5 component? even more, how to do this with a compiler that doesn't understand floating point in the first place? i've tried googling this. suprisingly there's not much out there on implementation specifics.
Advertisement

Think of it this way:

The fixed point representation (whole and fractional part) is the real value multiplied by 65536 (in this case), and then truncated to integer.

So

0.5 * 65536 =

32768 =

1/2 in 16.16 fixed point notation

cool.
but what if the compiler doesn't allow multipying 65536 by 0.5

ie. the compiler doesnt understand the floating pt number 0.5
Your compiler will support floating point types. If your processor does not support floating point arithmetics, the compiler will have to add additional functions to emulate the operations. For instance the gcc cross compiler for H8/300 uses functions from libgcc.a to emulate floating point operations.

Your fixed point arithmetic class may look something like this:
class Fixed {  // int32 is a typedef for a 32 bit integer type  typedef int32 ElemT;  ElemT value;  enum {    BITS = sizeof(ElemT) * 4,  // create n.n fixed point numbers (n = BITS)    ONE = (ElemT)1 << BITS     // fixed point value of 1.0  };public:  ...  Fixed(const double d) : value((ElemT)(d*ONE)) {}  ...};


Using the conversion ctor you can initialise your fixed point value with floating point constants:
Fixed fixed(1.5);


If your compiler is smart enough (i.e. gcc is), the double value will be converted at compile-time. The result is, that only an integer constant is stored in the private value field. Also no additional code for fp emulation (i.e. conversion to integer) is added by the compiler.
Quote:Original post by Rockoon1

Think of it this way:

The fixed point representation (whole and fractional part) is the real value multiplied by 65536 (in this case), and then truncated to integer.

So

0.5 * 65536 =

32768 =

1/2 in 16.16 fixed point notation

if you had a number such as 34.829.
it would be:
var i = 34 << 16;var j = .829 * 65536;//now how would you convert it back to decimal form?var a = i >> 16;var b = j / 65536; // is that right?


is there a better way?

Beginner in Game Development?  Read here. And read here.

 

Quote:Original post by Alpha_ProgDes
var b = j / 65536; // is that right?



You need: b = j % 65536, since j / 65536 == j >> 16;
Quote:Original post by bakery2k1
Quote:Original post by Alpha_ProgDes
var b = j / 65536; // is that right?



You need: b = j % 65536, since j / 65536 == j >> 16;

why not: j / 65536.0 ?
i'm not at a compiler, but why mod and not division?
will mod give me 829? if j is an int and less than 65536 then i guess b would then equal 0. hmm.... need more practice.

Beginner in Game Development?  Read here. And read here.

 

Quote:Original post by GekkoCube
cool.
but what if the compiler doesn't allow multipying 65536 by 0.5

ie. the compiler doesnt understand the floating pt number 0.5


I suspect most people are ignoring your "the compiler doesn't understand floating point math".

If it doesn't understand floating point math, you will have to use rationals of some kind to describe your numbers.

Either
A> When you want 0.5, work out what the value of the .16 portion will be outside of the compiler, or
B> Implement fixed-point division, and represent 0.5 as "fixed point 1 divided by fixed point 2".

Let a and b be fixed point numbers. Let A and B be the corresponding 32 bit integers. Ie A = a*2^16, B = b*2^16.

Then
a/b
= (A/2^16) / (B/2^16)
= A/B

which is rather useful. =)

Now write yourself the function:
#define STR_(x) #x#define STR(x) STR_(x)FixedPoint Rational( int top, int bottom, char const** error) {  if (error && *error) return FixedPoint();  if (bottom==0) {    if (error) *error = "Divide by zero error! [" __FILE__ "]:(" STR(__LINE__) ")\n"    return FixedPoint();  }  // implement "top divided by bottom" in here}


Then, you can have:
FixedPoint x = 1 + Rational(1,2);

or
FixedPoint x = Rational(3,2);

and have it work.

If you wanted to encode 0.47732, you would:
FixedPoint x = Rational(47732, 100000);

Quote:Original post by Alpha_ProgDes
Quote:Original post by bakery2k1
Quote:Original post by Alpha_ProgDes
var b = j / 65536; // is that right?



You need: b = j % 65536, since j / 65536 == j >> 16;

why not: j / 65536.0 ?
i'm not at a compiler, but why mod and not division?
will mod give me 829? if j is an int and less than 65536 then i guess b would then equal 0. hmm.... need more practice.


j / 65536 will give you j >> 16, which equals, in this case, 34.
j % 65536 will give you .829 * 65536, which is the fractional part.
You obviously cannot get .829 exactly, since as an integer that will round to 0 or 1.

This topic is closed to new replies.

Advertisement