Reputation: 47945
I've both the value and step numbers given in float, such as:
double step = 0.4;
double value = 47.7121;
I need to return, for each value and step pair I give, the nearest representable float number multiple of the step.
So here's some expected results:
step = 0.4;
value = 47.7121;
===> it must snap to 47.6
result = 47.60000000000000142108547152020037174224853515625
step = 0.1;
value = 47.9435;
===> it must snap to 47.9
result = 47.89999999999999857891452847979962825775146484375
I'm able to do this only with rational numbers (not float), in this form:
#include <iostream>
#include <math.h>
inline double SnapValue(double value, int numerator, int denominator) {
return round(value * denominator / numerator) * numerator / denominator;
}
int main() {
std::cout.precision(100);
std::cout << "result: " << SnapValue(47.7121, 2, 5) << std::endl; // step = 0.4, value 47.7121
std::cout << "result: " << SnapValue(47.9435, 1, 10) << std::endl; // step = 0.1, value 47.9435
return 0;
}
But, as I said, I don't have any rational numbers to start with, only float. How would you do this?
Upvotes: 2
Views: 545
Reputation: 18807
A very simple solution, using std::round
:
#include <cmath>
double nearest_step(double value, double step)
{
return std::round(value/step)*step;
}
Be aware that there is no floating point number with (exactly) the value 0.1
. The closest double
to 1./10
is 0.1000000000000000055511151231257827021181583404541015625
, i.e., you will get slightly bigger numbers than expected most of the time. (Also, the result of the division is usually not exact, so in a few corner cases it may get rounded to the wrong direction.)
Upvotes: 0
Reputation: 10151
I would do it like this
Your fist example:
double step = 0.4;
(float) (((int) (47.7121d / step + step / 2)) * step);
-> 47.6
Your second example:
double step = 0.1;
(float) (((int) (47.9435d / step + step / 2)) * step);
-> 47.9
This part is needed to get the nearest: + step / 2
.
Upvotes: 1