Jump to content
  • Advertisement
Sign in to follow this  
GekkoCube

fixed point math - the fraction component question.

This topic is 4620 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
Quote:
Original post by Alpha_ProgDes
var b = j / 65536; // is that right?



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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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);

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!