210
votes

I have a program in C++ (compiled using g++). I'm trying to apply two doubles as operands to the modulus function, but I get the following error:

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

Here's the code:

int main() {
    double x = 6.3;
    double y = 2;
    double z = x % y;
}
4
As has been noted, fmod() provides the necessary function. As has not yet been noted, it's important to realize that rounding errors in the second operand of fmod may cause unexpected behaviors. For example, fmod(1, 0.1); should mathematically be zero, but will in fact be almost 0.1. The extent of error goes up with the magnitude of the quotient. For example, fmod(9E14, 0.1); evaluates to about 0.05, which is from a mathematical standpoint just plain wrong. - supercat
@supercat more details would be awesome. I think have an idea of what's on behind the scenes to cause what you say to be true, but it would be good to see the reasons for why what you say is true; would be interesting to see how it works behind the scenes (I think I understand but could very easily be wrong). - RastaJedi
Floating-point values represent exact integer multiples or fractions of powers of two. For example, the integer literal 0.1 is exactly 3602879701896397/36028797018963968 (the latter value is a power of two). fmod(x,0.1) will divide x by that precise fraction and take the remainder, rather than dividing by the numerical value "one tenth". - supercat

4 Answers

305
votes

The % operator is for integers. You're looking for the fmod() function.

#include <cmath>

int main()
{
    double x = 6.3;
    double y = 2.0;
    double z = std::fmod(x,y);

}
39
votes

fmod(x, y) is the function you use.

5
votes

Use fmod() from <cmath>. If you do not want to include the C header file:

template<typename T, typename U>
constexpr double dmod (T x, U mod)
{
    return !mod ? x : x - mod * static_cast<long long>(x / mod);
}

//Usage:
double z = dmod<double, unsigned int>(14.3, 4);
double z = dmod<long, float>(14, 4.6);
//This also works:
double z = dmod(14.7, 0.3);
double z = dmod(14.7, 0);
double z = dmod(0, 0.3f);
double z = dmod(myFirstVariable, someOtherVariable);
4
votes

You can implement your own modulus function to do that for you:

double dmod(double x, double y) {
    return x - (int)(x/y) * y;
}

Then you can simply use dmod(6.3, 2) to get the remainder, 0.3.