fouadalnoor
fouadalnoor

Reputation: 217

How do you multiply two fixed point numbers?

I am currently trying to figure out how to multiply two numbers in fixed point representation.

Say my number representation is as follows:

[SIGN][2^0].[2^-1][2^-2]..[2^-14]

In my case, the number 10.01000000000000 = -0.25.

How would I for example do 0.25x0.25 or -0.25x0.25 etc?

Hope you can help!

Upvotes: 5

Views: 25206

Answers (3)

Randall Cook
Randall Cook

Reputation: 6776

Here's a simple example in C:

int a =  0.25 * (1 << 16);
int b = -0.25 * (1 << 16);
int c = (a * b) >> 16;
printf("%.2f * %.2f = %.2f\n", a / 65536.0, b / 65536.0 , c / 65536.0);

You basically multiply everything by a constant to bring the fractional parts up into the integer range, then multiply the two factors, then (optionally) divide by one of the constants to return the product to the standard range for use in future calculations. It's like multiplying prices expressed in fractional dollars by 100 and then working in cents (i.e. $1.95 * 100 cents/dollar = 195 cents).

Be careful not to overflow the range of the variable you are multiplying into. Your constant might need to be smaller to avoid overflow, like using 1 << 8 instead of 1 << 16 in the example above.

Upvotes: 2

phuclv
phuclv

Reputation: 41774

You should use 2's complement representation instead of a seperate sign bit. It's much easier to do maths on that, no special handling is required. The range is also improved because there's no wasted bit pattern for negative 0. To multiply, just do as normal fixed-point multiplication. The normal Q2.14 format will store value x/214 for the bit pattern of x, therefore if we have A and B then

\frac{A}{2^{14}}\times\frac{B}{2^{14}} = \frac{A \times B}{2^{14}}\times \frac{1}{2^{14}}

So you just need to multiply A and B directly then divide the product by 214 to get the result back into the form x/214 like this

AxB = ((int32_t)A*B) >> 14;

A rounding step is needed to get the nearest value. You can find the way to do it in Q number format#Math operations. The simplest way to round to nearest is just add back the bit that was last shifted out (i.e. the first fractional bit) like this

AxB = (int32_t)A*B;
AxB = (AxB >> 14) + ((AxB >> 13) & 1);

You might also want to read these

With 2 bits you can represent the integer range of [-2, 1]. So using Q2.14 format, -0.25 would be stored as 11.11000000000000. Using 1 sign bit you can only represent -1, 0, 1, and it makes calculations more complex because you need to split the sign bit then combine it back at the end.

Upvotes: 6

StilesCrisis
StilesCrisis

Reputation: 16290

Multiply into a larger sized variable, and then right shift by the number of bits of fixed point precision.

Upvotes: 3

Related Questions