📅 2018-Aug-17 ⬩ ✍️ Ashwin Nanjappa ⬩ 🏷️ float, round ⬩ 📚 Archive
The round function available in C and C++ uses the rounding mode called round half away from zero. In this mode, the floating point value is rounded to the nearest integer value. When the floating point value is exactly midway, then the integer value away from zero is picked.
Many applications require the rounding mode to be round half to even. In this mode, when the floating point value is midway, the integer value that is even is chosen.
If you need round half to even, then you use the nearbyint or rint methods and set the rounding mode to FE_TONEAREST
before you use them. For more information on these rounding modes, see this post.
#include <cfenv>
#include <cmath>
std::fesetround(FE_TONEAREST); // This is the default rounding mode for std::nearbyint
std::nearbyint(3.5f); // Result is 4
std::nearbyint(4.5f); // Result is 4
FE_TONEAREST
is the default rounding mode, so you do not need to actually set it. Unless you believe it was set to some other rounding mode earlier in your code.
If you wish to do this rounding manually, then here is one possible implementation with test code:
#include <array>
#include <cmath>
#include <iostream>
float roundHalfToEven(float f)
{const float r = round(f); // Result is round-half-away-from-zero
const float d = r - f; // Difference
// Result is not half, RHAFZ result same as RHTE
if ((d != 0.5f) && (d != -0.5f))
{return r;
}
// Check if RHAFZ result is even, then RHAFZ result same as RHTE
if (fmod(r, 2.0f) == 0.0f)
{return r;
}
// Switch to even value
return f - d;
}
int main()
{const std::array<float, 8> fvals {{-5.5, -4.5, -3.5, -0.5, 0.5, 3.5, 4.5, 5.5}};
for (float f : fvals)
{const float r = roundHalfToEven(f);
std::cout << "roundHalfToEven(" << f << "): " << r << std::endl;
}
return 0;
}