After some experimentation, I think I can provide a partial answer. Let me
rephrase the question: Write a function
int bin(double x, double m)
which computes
int(floor(x/m))
exactly. Assume m is positive and that the result is in the range of
int.
The first attempt is
int bin0(double x, double m) {
return int(std::floor(x / m));
}
but this fails for the case m = 360.0 and x = -denorm_min (0 is
returned instead of -1).
Since this failure is just for x close to zero, the second attempt is
int bin1(double x, double m) {
int n = int(std::floor(x / m));
return n == 0 && x < 0 ? -1 : n;
}
I believe this returns the exact answer provided that n * m is
exactly representable as a double. For m = 360.0, this includes all
n representable as a 32-bit integer. Am I right? A proof would be
nice!
If this condition doesn't hold, e.g., m = 0.1, then the best I can
come up with is
int bin2(double x, double m) {
double z = std::fmod(x, m);
return int(std::floor((x - z)/m + 0.5)) + (z < 0 ? -1 : 0);
}
Does this always return the correct result? Is there some "cleaner"
solution?
ADDENDUM: In my application I only needed to get the parity of the
bin number (even or odd). (My application is measuring the area of a
geodesic polygon and I need to keep track of whether an edge encircles
the pole an even or odd number of times.) So chux's suggestion to use
remquo is a good one. Unfortunately (1) std::remquo requires C++11 and
(2) more seriously, the glibc implementation of remquo is buggy; see
this bug report. So I end up doing essentially
int binparity(real x, real m) {
// return the parity of int(floor(x/m))
x = std::fmod(x, 2 * m);
return (x >= 0 && x < m) || x < -m ? 0 : 1
}