Why does modulus division (%) only work with integers?

C++C

C++ Problem Overview


I recently ran into an issue that could easily be solved using modulus division, but the input was a float:

> Given a periodic function (e.g. sin) and a computer function that can only compute it within the period range (e.g. [-π, π]), make a function that can handle any input.

The "obvious" solution is something like:

#include <cmath>

float sin(float x){
    return limited_sin((x + M_PI) % (2 *M_PI) - M_PI);
}

Why doesn't this work? I get this error:

error: invalid operands of types double and double to binary operator %

Interestingly, it does work in Python:

def sin(x):
    return limited_sin((x + math.pi) % (2 * math.pi) - math.pi)

C++ Solutions


Solution 1 - C++

Because the normal mathematical notion of "remainder" is only applicable to integer division. i.e. division that is required to generate integer quotient.

In order to extend the concept of "remainder" to real numbers you have to introduce a new kind of "hybrid" operation that would generate integer quotient for real operands. Core C language does not support such operation, but it is provided as a standard library fmod function, as well as remainder function in C99. (Note that these functions are not the same and have some peculiarities. In particular, they do not follow the rounding rules of integer division.)

Solution 2 - C++

You're looking for fmod().

I guess to more specifically answer your question, in older languages the % operator was just defined as integer modular division and in newer languages they decided to expand the definition of the operator.

EDIT: If I were to wager a guess why, I would say it's because the idea of modular arithmetic originates in number theory and deals specifically with integers.

Solution 3 - C++

I can't really say for sure, but I'd guess it's mostly historical. Quite a few early C compilers didn't support floating point at all. It was added on later, and even then not as completely -- mostly the data type was added, and the most primitive operations supported in the language, but everything else left to the standard library.

Solution 4 - C++

The modulo operator % in C and C++ is defined for two integers, however, there is an fmod() function available for usage with doubles.

Solution 5 - C++

The constraints are in the standards:

C11(ISO/IEC 9899:201x) §6.5.5 Multiplicative operators

>Each of the operands shall have arithmetic type. The operands of the % operator shall have integer type.

C++11(ISO/IEC 14882:2011) §5.6 Multiplicative operators

>The operands of * and / shall have arithmetic or enumeration type; the operands of % shall have integral or enumeration type. The usual arithmetic conversions are performed on the operands and determine the type of the result.

The solution is to use fmod, which is exactly why the operands of % are limited to integer type in the first place, according to C99 Rationale §6.5.5 Multiplicative operators:

>The C89 Committee rejected extending the % operator to work on floating types as such usage would duplicate the facility provided by fmod

Solution 6 - C++

try fmod

Solution 7 - C++

The % operator gives you a REMAINDER(another name for modulus) of a number. For C/C++, this is only defined for integer operations. Python is a little broader and allows you to get the remainder of a floating point number for the remainder of how many times number can be divided into it:

>>> 4 % math.pi
0.85840734641020688
>>> 4 - math.pi
0.85840734641020688
>>> 

Solution 8 - C++

The % operator does not work in C++, when you are trying to find the remainder of two numbers which are both of the type Float or Double.

Hence you could try using the fmod function from math.h / cmath.h or you could use these lines of code to avoid using that header file:

float sin(float x) {
 float temp;
 temp = (x + M_PI) / ((2 *M_PI) - M_PI);
 return limited_sin((x + M_PI) - ((2 *M_PI) - M_PI) * temp ));

}

Solution 9 - C++

"The mathematical notion of modulo arithmetic works for floating point values as well, and this is one of the first issues that Donald Knuth discusses in his classic The Art of Computer Programming (volume I). I.e. it was once basic knowledge."

The floating point modulus operator is defined as follows:

m = num - iquot*den ; where iquot = int( num/den )

As indicated, the no-op of the % operator on floating point numbers appears to be standards related. The CRTL provides 'fmod', and usually 'remainder' as well, to perform % on fp numbers. The difference between these two lies in how they handle the intermediate 'iquot' rounding.

'remainder' uses round-to-nearest, and 'fmod' uses simple truncate.

If you write your own C++ numerical classes, nothing prevents you from amending the no-op legacy, by including an overloaded operator %.

Best Regards

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBrendan LongView Question on Stackoverflow
Solution 1 - C++AnTView Answer on Stackoverflow
Solution 2 - C++Doug StephenView Answer on Stackoverflow
Solution 3 - C++Jerry CoffinView Answer on Stackoverflow
Solution 4 - C++Mark ElliotView Answer on Stackoverflow
Solution 5 - C++Yu HaoView Answer on Stackoverflow
Solution 6 - C++justinView Answer on Stackoverflow
Solution 7 - C++AndrewView Answer on Stackoverflow
Solution 8 - C++ShashankView Answer on Stackoverflow
Solution 9 - C++LoveView Answer on Stackoverflow