Home > database >  can anyone explain me the maths of this code?
can anyone explain me the maths of this code?

Time:07-08

Consider

x_min as -12.5,
x_max as 12.5,
bits as 8,
x is any value between -12.5 to 12.5 ,

Can someone explain me the math's of this snippet??


int float_to_uint(float x, float x_min, float x_max, unsigned int bits) 
{ 
  float span = x_max - x_min; 

  return (int) ((x- x_min)*((float)((1<<bits)/span)));
}

CodePudding user response:

If we ignore rounding, types and other little details, you could rearrange the separate parts a bit:

(x-x_min) / (x_max-x_min) * (1<<bits)

This is basically scaling x to values of 0..2^bits (=256) depending on where x is within x_min..x_max.

  x   |  result
------ ----------
-12.5 |   0
 ...  |  
  0   | 128
 ...  |  
 12.5 | 256

CodePudding user response:

The goal of the function is to map values in the range x_min to x_max to values 0 to 2^bits.

(int) ((x- x_min) / span * (1<<bits));

But there is some trickery being used here to help the optimizer. The last two values are re-aranged and computed first. Mathematically it's the same but with floats it will round differently. A difference so minor there is actually a compiler flag allowing the compiler to ignore it (fast-math).

(int) ((x- x_min)    *    ((1<<bits) / span));

The cast to float is pointless as arithmetic promotion already turns 1<<bits into a float and float / float remains float.

Now you might ask: What is the point of this transformation? The result is the (about) the same.

Here is my thought on that: In the source the bits, x_min and x_max will be literals or constants. So span is known at compile time too. The transformation allows the compiler to inline that function and compute (1<<bits) / span) at compile time. That leaves only one float subtraction and multiplication at runtime. It will therefore generate code that runs noticeable faster on something like an Arduino that has no FPU.

  • Related