Why does this code choose to multiply by (1 / 16777216) instead of dividing by 16777216?

Viewed 189

I was looking at how Numpy implements the random module and saw the following function to generate a float32 from a random uint32:

static NPY_INLINE float next_float(bitgen_t *bitgen_state) {
  return (next_uint32(bitgen_state) >> 8) * (1.0f / 16777216.0f);
}

I don't get why they multiply by (1.0f / 16777216.0f) here, instead of simply dividing by 16777216.0f.

Edit: As we can see from compiling the two ways of writing this function, there seems to be no difference in the generated code. So, this does not seem to be a case of "float multiplication is faster than float division".

1 Answers

Because it is faster to multiply than divide in most CPUs.

(1.0f / 16777216.0f) is converted into a constant during compilation and then the computer just needs to use the multiplication in runtime.

In C++, the compiler can be set to do this optimization automatically with --ffast-math flag, without the need to insert x*(1/y) in the code. However, it may not be safe since the result is not the same as simply dividing (due to rounding errors). By explicitly adding x*(1/y) you are manually doing what the compiler would do with this flag.

Side note: As pointed by harold, if the division result can be exactly represented in float, the compiler may do this optimization automatically, even without --ffast-math.

Related