Fixed point math
Displaying 1-5 of 5 total.
1
Please enter a numerical value for the importance of this sticky.
Enter 0 to unsticky.
Beni

I read aen's tutorial, maybe I'm missing something, but I still don't understand how to do multiplication and division with 16.16 fixed point numbers.

This is the best I could come up with.

int FPmult(int a, int b)
{
return (a * (b>>16));
}

int FPdiv(int a, int b)
{
return (a / (b>>16));
}

But this leaves out the fractional part of b. Is there a better way?

Posted on 2004-11-24 08:24:30

basil

b>>16 is bitshifting DOWN, so you're dividing by a large number and losing information. The idea is that, for example,
10.1 * 4 = 40.4 which gets rounded down to 40. However, if you go
(10.1 * 10) * 4 = 404, no information has been lost. You just need to remember to divide back down by 10 when you use it.
And since bitshifting is just fast multiplication/division, it's the recommended way of doing this trick. Your multiply function will work if you bitshift UP, and the divide should look like (a<<16) / b. Just remember to shift the results back down when you use them.

Posted on 2004-11-24 10:10:22

Beni

An int is 32 bits right? So (a<<16) would cause the fractional part to move to the first 16 bits. And the whole part would just disappear right?

1.5 << 16 = 32768.0
32768.0 >> 16 = 0.5
1.5 becomes 0.5

I was thinking about it though and I have a better solution for the multiplication.
(a>>8) * (b>>8);

I'm still working on the division though.

Posted on 2004-11-25 01:23:54

basil

1.5 << 16
= 1.5 * (2^16)
= 98304
= my_result

my_result >> 16 = 1 because verge rounded down, but the precision is still there. For example:

(my_result *10) >> 16 = 15

And also,
(a>>8) * (b>>8)
= (a) * (2^8) * (b) * (2^8)
= (a) * (b) * (2^8)*(2^8)
= (a) * (b) * (2^16)
= (a)*(b) << 16

So by splitting it up like that you're doing the same thing but in two operations rather than one.

Just remember,
treat a << b as a*(2^b)
and a>>b as a/(2^b)

And remember that information right of the decimal point will be rounded off unless you multiply by a big enough number to get that information left of the decimal point. Confusing? Ask away if it is.

Posted on 2004-11-25 01:40:14 (last edited on 2004-11-25 01:42:42)

Beni

1.5 in fixed point notation lookes like this in binary

00000000000000011000000000000000

So 1.5 << 16 looks like this

110000000000000000000000000000000

But that is 33 bits. So the first bit will just fall off and it becomes this

10000000000000000000000000000000

Then when you shift down 16 again it becomes this

00000000000000001000000000000000

Which is 0.5 in fixed point notation.

Oh, by the way, it looks like I'm not paying attention to the first bit as the negative sign, but in my actual code, I've handled that. But I still need a good function for division.

Posted on 2004-11-25 03:18:50


Displaying 1-5 of 5 total.
1
 
Newest messages

Ben McGraw's lovingly crafted this website from scratch for years.
It's a lot prettier this go around because of Jon Wofford.
Verge-rpg.com is a member of the lunarnet irc network, and would like to take this opportunity to remind you that regardless how babies taste, it is wrong to eat them.