239

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;
}
hichris123
  • 10,145
  • 15
  • 56
  • 70
Bhaxy
  • 5,346
  • 10
  • 39
  • 41
  • 16
    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 Jun 27 '13 at 21:32
  • 1
    @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 Mar 18 '16 at 04:30
  • 4
    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 Mar 18 '16 at 14:26
  • 1
    Possible duplicate: [Why does modulus division (%) only work with integers?](https://stackoverflow.com/q/6102948/253056) – Paul R Jan 02 '18 at 22:55

5 Answers5

335

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);

}
Aykhan Hagverdili
  • 28,141
  • 6
  • 41
  • 93
Mysticial
  • 464,885
  • 45
  • 335
  • 332
  • 1
    I am programming in C++ for Qt and fmod has a bug there. The result of fmod(angle, 360) can be 360 (WAT?!) – Paul May 30 '17 at 07:39
  • 9
    @Paul: That's probably not a bug. If `angle` is, say, `359.9999999`, then both `angle` and `fmod(angle, 360)` are likely to be displayed as `360`. (Add more 9s as needed.) Try printing the values with, say, 50 digits of precision. – Keith Thompson Jan 02 '18 at 22:42
  • @Paul Qt's QString::format will round. If it is that critical, you will either have to round yourself or check the output for "360" and replace it with your own value. – jfh Mar 26 '20 at 21:30
  • 1
    @Rohan `main(void)` is not necessary in `C++` (it's C legacy) and your edit isn't improving anything else either. I reverted it back. – Aykhan Hagverdili Jan 22 '21 at 16:51
  • 2
    This doesn't work for negative numbers. `std::fmod(-1.0, 2 * M_PI)` returns `-1.0`, I would expect approximately `5.28`. – Donald Duck Oct 08 '22 at 10:06
40

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

MSN
  • 53,214
  • 7
  • 75
  • 105
8

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.

Mystical
  • 2,505
  • 2
  • 24
  • 43
5

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);
Sceptical Jule
  • 889
  • 1
  • 8
  • 26
0

Here is a function that also works with both positive and negative numbers:

#include <cmath>

inline double nmod(double x, double y) {
    return std::fmod(std::fmod(x, y) + y, y);
}

It will always return a positive number if x is negative or positive.

Note that if y is negative, the returned value will be negative. If you need a function that will return a positive in any case, then one need to use std::fabs() on y, i.e.:

inline double nmod2(double x, double y) {
    return std::fmod(std::fmod(x, y) + std::fabs(y), y);
}
Pamputt
  • 173
  • 1
  • 11