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.