Floating-point operations like x=a/b
are usually not exactly representable so the CPU has to do rounding. Is it possible to get the two floats x_low
and x_up
that are respectively the highest floating point less or equals than the exact value of a/b
and the lowest floating point higher or equals than a/b
?
Some of the conditions are :
a
,b
,x_low
,x_up
andx
arefloat
a
andb
are positive, integers (1.0f
,2.0f
, etc)
CodePudding user response:
This will give you a bounds that might be too large:
#include <cmath>
#include <utility>
template<typename T>
std::pair<T, T> bounds(int a, int b) {
T ta = a, tb = b;
T ta_prev = std::nexttoward(ta), ta_next = std::nextafter(ta);
T tb_prev = std::nexttoward(tb), tb_next = std::nextafter(tb);
return std::make_pair(ta_prev / tb_next, ta_next / tb_prev);
}
CodePudding user response:
An easy way to do it is to do the division in higher precision and get the upper/lower bound on conversion to float:
struct float_range {
float lower;
float upper;
};
float_range to_float_range(double d) {
float as_float = static_cast<float>(d);
double rounded = double{as_float};
if (std::isnan(as_float) || rounded == d) {
// No rounding done
return { as_float, as_float };
}
if (rounded < d) {
// rounded down
return { as_float, std::nextafter(as_float, std::numeric_limits<float>::infinity()) };
}
// rounded up
return { std::nextafter(as_float, -std::numeric_limits<float>::infinity()), as_float };
}
float_range precise_divide(float a, float b) {
return to_float_range(double{a}/double{b});
}