简体   繁体   中英

How to return the nearest representable float number multiple of another float number?

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?

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 .

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 , ie, 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.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM