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.
