Reputation: 341
I've been looking for examples on how to wrap a float between two numbers, similar to how you can do with integers using modulus. Examples I've found either involve using fmod to just find the remainder past the decimal point, assuming it's for a circle and doing pi-based math, among other things that didn't quite do what I needed. Finally, I just wrote this:
float fwrap(float x, float a0, float a1)
{
float mx = max(a0, a1);
float mn = min(a0, a1);
float nw = x;
while(nw < mn) nw += mx - mn;
while(nw > mx) nw -= mx - mn;
};
It works, but I'm sure if the original value is too far from the range, it'll slow thinks down, so is there a faster way to do this that doesn't involve loops?
All I need it to do is to wrap a number around a range when it goes beyond them, for instance, if a0
is 10 and a1
is 20, then if x
is 25, it should return 15, but it should also work with floats, so if x
is 8.5, it should return 18.5.
Upvotes: 1
Views: 1875
Reputation: 154156
Is there a more efficient way to wrap a float?
Use std::fmod()
.
#include <cmath>
float fwrap(float x, float min, float max) {
if (min > max) {
return fwrap(x, max, min);
}
return (x >= 0 ? min : max) + std::fmod(x, max - min);
}
You could even make it generic, to work with other floating-point types:
#include <cmath>
#include <concepts>
#include <utility>
template<std::floating_point F>
F fwrap(F x, F min, F max) {
if (min > max) {
std::swap(min, max); // alternative to recursion
}
return (x < 0 ? max : min) + std::fmod(x, max - min);
}
Upvotes: 3