0

I know with normal integers you can divide by bitshifting to the right. I'm wondering if theres an easy way to do the same with numbers that aren't perfect integers.

3 Answers3

4

ldexp, ldexpf, and ldexpl do this for doubles, floats, and long doubles respectively. Alternatively, if you have a specific power of two in mind (say, 4), it's probably best to just divide the usual way:

whatever / 4
user2357112
  • 260,549
  • 28
  • 431
  • 505
0

There is a function ldexp (and siblings) that allows you to "multiply by powers of two" (including negative ones), this is not the same optimisation as using shifts for integers. For powers of two, all double values are "perfect" for both X and 1/X (because if X is 2n, then 1/X = 2-n, both of which are fine to store as a floating point number in IEEE-754 or any other binary floating point format), so there won't be any odd rounding, which means the compiler should be able to replace the divide by a multiply operation - in my experiments, it indeed does.

To manipulate the exponent of floating point values is generally detrimental to performance compared to the "apply multiply by 1/X".

The function ldexp is a few dozen instructions long in glibc, with several branches and a call in the code. It is highly unlikely you'll find any benefit from calling ldexp, as well as confusing people who don't know that x = ldexp(x, -1); is the same as x /= 2.0;.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
0

Just use

double x = 7;
x *= 2;
x /= 2;
assert(x == 7.0);

or

double y = 5;
y = 2*x + 0.5*y;
assert(y == 16.5);

or

double z = 2.5*x;
assert(z == 17.5);

Why? Because your computer can represent all powers of two as floating point values (as long as that power does not exceed the limit of the exponent, that is), and it will do so. Consequently, all of the calculations above are precise, there is no rounding error in the constants. All the assert()s are guaranteed to succeed.

Of course, you can achieve the same effect by doing bit manipulations, but current floating point hardware can do a multiplication within a nanosecond, and it handles all special cases correctly. If you do the bit fiddling, you will either waste time, or handle the special cases incorrectly. So don't even try.

cmaster - reinstate monica
  • 38,891
  • 9
  • 62
  • 106