You said, you scale both operands by multiplying with 2^14. Then you have to scale the result by dividing through 2^28. For example:

C++

double a = 1.5; double b = 3.6; int as = (int) (a *(2<<14)); int bs = (int) (b *(2<<14)); int rss = as * bs; double r = rss / (2<<28);

If you want to remain in your integer based 2^14 system you can do so by scaling the result back by dividing by 2^14.

C++

int as = (int) (a *(2<<14)); int bs = (int) (b *(2<<14)); int rs = (as * bs) >> 14;

This way the result will be scaled also by 2^14. You can easily convert it to a double by

C++

double r = ((double)rs) / (2<<14);

Now to division: If you want to divide two quantities that have been both scaled by 2^14, you should first scale the dividend by an additional factor of 2^14, otherwise the result will be unscaled and in your example mostly 0 or 1. Here is how to do it:

C++

int as = (int) (a *(2<<14)); int bs = (int) (b *(2<<14)); int rs = (a << 14) / b;

Again your result will be scaled by 2^14 and can be converted back to double as shown above.

Note that in the case of 32-bit integers, you will be limited to in the number space to an integer part of smaller than 8. This is, because your initial result will be scaled by 2^28, leaving just 4 bits for the integer part, one of which is the sign bit. Hence you might consider using type long long for your integer operations.