A Euclidian Modulus function for C++

For anyone who has tried to apply a modulus operator with negative numbers, you have probably discovered that the c++ "%" operator and fmod functions don't really cut it, as they are truncated modulus functions that tend to have poor representativeness.

I wasn't able to find a proper euclidian modulus operator for floating point operations, so I wrote a small function that I have tested (only for floating point types).

1
2
3
4
5
6
7
template <typename T> T const EucFMod(T const dividend,T const divisor)
{
  assert(divisor > 0.0);
  T const quotient = std::ceil(dividend / divisor);
  T const remainder = divisor * (1 + dividend / divisor - quotient);
  return remainder == divisor ? 0.0 : remainder;
}


Any observations or recommendations would be appreciated. Or if you know of some inbuilt/more efficient alternative please let me know.
Last edited on
What exactly is representativeness?
The tendency of a construct to be representative. The mod function in c++ was designed to quickly and efficiently restrict the magnitude of an unsigned integer to some range for the purpose of (presumably) indexing some array or contiguous series of objects. Its representativeness in natural, mathematical, or physical situations however is poor though, as the truncated modulus is unable to represent a continuous loop across the series of all signed integers, which is what I'm trying to achieve with the euclidean mod.
remainder == divisor Floating point comparsion problem could arise.
Actually remainder > divisor can return true because of rounding problems before.
The assembly instruction for modulus is actually the exact same instruction for division. The CPU performs the operation, the quotient goes into one part of, or another register (depending on the size of the type), and the remainder into another.

I believe it's up to the hardware how the behavior is defined.
Last edited on
I believe it's up to the hardware how the behavior is defined.
What a wonderful idea to have mathematic formula result change depending on hardware you launch it.
Last edited on
If both operands are nonnegative then the remainder is nonnegative; If if not, the sign of the remainder is implementation-defined.

http://stackoverflow.com/questions/7594508/modulo-operator-with-negative-values

Modulus is very efficient. It's the same operation as division, although division can be optimized by turning it into multiplication. Since it's a direct CPU instruction, it is very very fast. Much faster than a software algorithm. It is strange though for operands of different signs, the sign of the result is implementation defined.
Last edited on
It is strange though for operands of different signs, the sign of the result is implementation defined.
That is because this operation works different on different processors, and it should be fast low-level operation.

Still It would be a disaster to have undefined result of math operation, so we have to fall to software algorithms
For example this is formula for always positive remainder, used in day of week calculation in C++:
1
2
3
4
remainder = (divid % divis + divis) % divis;
//or
int temp = divid % divis;
remainder = (temp < 0)?(temp + divis):temp;

The same formula in Python: remainder = divid % divis
Because Python defines result of nonpositive modlus operation
Opinion: use a combination of MiiNiPaa and ausairman:
1
2
3
4
5
6
7
template <typename T> T const EucFMod(T const dividend,T const divisor)
{ assert(divisor > 0); //note we compare to 0, not 0.0
  T result = dividend % divisor;
  if (result<0)
    result+=divisor;
  return result;
}


Note: I am against taking moduli with respect to negative numbers. This calls for a programming mathematical error.
Also, I prefer that the comparison be to 0, not to 0.0: if I am to use with a LargeInteger class, I don't want to compare LargeInteger to doubles.

This solution will produce effective code with integers, but will also work great with far more complex data structures, say, one-variable polynomials over the rationals.
Last edited on
This calls for a programming mathematical error.
Use of "round result of division with remainder towards —∞, remainder is always non-negative and in range of [0; divisor)" is considered default between my country mathematicians because it allows for continuous stable series in regards for both positive and negative function arguments and generalizes some relations on numbers ∈ ℝ.
Last edited on
Topic archived. No new replies allowed.