91

One of my pet hates of C-derived languages (as a mathematician) is that

(-1) % 8 // comes out as -1, and not 7

fmodf(-1,8) // fails similarly

What's the best solution?

C++ allows the possibility of templates and operator overloading, but both of these are murky waters for me. examples gratefully received.

TemplateRex
  • 69,038
  • 19
  • 164
  • 304
P i
  • 29,020
  • 36
  • 159
  • 267
  • 1
    I don't think this is quite a "duplicate" of http://stackoverflow.com/questions/828092/python-style-integer-division-modulus-in-c under the official definition. It's not true that this question's answers can be merged into that one's, because this question only asks about modulus, not also division. But I think this question is covered by that one, so it's close. My answer is there already, FWIW. – Steve Jessop Oct 23 '10 at 11:25
  • Maybe that thread should be split, as it asks two separate questions. the best way to do that might be to re-ask the division question separately and then point it towards that answer. I will leave it to someone who understands the mechanisms of this website better. – P i Oct 23 '10 at 15:45
  • 3
    @Pi owhere is `%` said to be the *modulo*... it's the *remainder*. – obataku Sep 09 '12 at 08:29
  • 1
    Here's another thread that this is a "duplicate" of: http://stackoverflow.com/questions/1082917/mod-of-negative-number-is-melting-my-brain Just for reference on this `%` problem. – leetNightshade Apr 06 '15 at 20:17
  • If you are only dividing powers of two then it might be a better idea to use and: `(-1) & 8 == 7` – Henricus V. Jul 18 '16 at 00:08
  • @Henry W. `(-1) & 8 == 7 `??? `(-1) & 8` will only result in 0 or 8, not 7. Perhaps you meant `(-1) & (8-1)`? – chux - Reinstate Monica Jul 25 '16 at 19:03

16 Answers16

80

First of all I'd like to note that you cannot even rely on the fact that (-1) % 8 == -1. the only thing you can rely on is that (x / y) * y + ( x % y) == x. However whether or not the remainder is negative is implementation-defined.

Reference: C++03 paragraph 5.6 clause 4:

The binary / operator yields the quotient, and the binary % operator yields the remainder from the division of the first expression by the second. If the second operand of / or % is zero the behavior is undefined; otherwise (a/b)*b + a%b is equal to a. If both operands are nonnegative then the remainder is nonnegative; if not, the sign of the remainder is implementation-defined.

Here it follows a version that handles both negative operands so that the result of the subtraction of the remainder from the divisor can be subtracted from the dividend so it will be floor of the actual division. mod(-1,8) results in 7, while mod(13, -8) is -3.

int mod(int a, int b)
{
   if(b < 0) //you can check for b == 0 separately and do what you want
     return -mod(-a, -b);   
   int ret = a % b;
   if(ret < 0)
     ret+=b;
   return ret;
}
ceztko
  • 14,736
  • 5
  • 58
  • 73
Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
  • I just tested the first chunk and that works, though I can't get my head around why! I would hesitate to use it, as I'm not sure whether it would work for *any* compiler implementation of % that satisfies the criterion of (x / y) * y + ( x % y) == x. where did you get that from, out of curiosity? Is that in the C standard? If it is robust, it may be preferable over my method (below) for integers in terms of speed. – P i Oct 23 '10 at 10:20
  • I am guessing there is a second criterion that |x%y| < |y|. so the specification for x%y would go: x%y (for int x, y) returns an integer r, s.t. (x / y) * y + r == x, and |r| < |y| – P i Oct 23 '10 at 11:07
  • @Ohmu: If you want to cover the second criterion change `if` to `while`. But it's practically unnecessary – Armen Tsirunyan Oct 23 '10 at 11:38
  • @Armen: The second criterion is what makes `if` work correctly. But your whole premise is dead wrong: **Integer division is well-defined in the C++ standard as using truncation toward zero, which guarantees that the sign of `x%y` is the same as the sign of `x`** – Ben Voigt Oct 23 '10 at 19:02
  • 2
    @Ohmu: Yes, that's in the C++ standard. For integral operands the / operator yields the algebraic quotient with any fractional part discarded; if the quotient a/b is representable in the type of the result, (a/b)*b + a%b is equal to a. – Ben Voigt Oct 23 '10 at 19:08
  • 5
    -1. It's been 11 years since this was implementation defined. ISO 9899:1999 defined it, and unfortunately chose the bad definition. – R.. GitHub STOP HELPING ICE Oct 23 '10 at 19:53
  • @Ben, @R.. C++03 paragraph 5.6 clause 4: < quote > The binary / operator yields the quotient, and the binary % operator yields the remainder from the division of the first expression by the second. If the second operand of / or % is zero the behavior is undefined; otherwise (a/b)*b + a%b is equal to a. If both operands are nonnegative then the remainder is nonnegative; **if not, the sign of the remainder is implementation-defined**.< end quote> What will you say to this? – Armen Tsirunyan Oct 23 '10 at 20:08
  • Great information Armen! Would you consider editing the knowledge contained in these comments back into your answer when it stabilises? It's a bit hidden here. – P i Oct 23 '10 at 21:14
  • @Ohmu: Good point, hopefully I'll avoid future downvotes... (got 2 already for this answer) – Armen Tsirunyan Oct 23 '10 at 21:16
  • You guys are quoting C++ standards. What's the simplest solution guaranteed to run on any C compiler? Armen you need to clarify your solution scope. – P i Oct 23 '10 at 21:43
  • 3
    @Armen: You conveniently deleted the footnote ... integer division follows the rules defined in the ISO Fortran standard, ISO/IEC 1539:1991, in which the quotient is always rounded toward zero. The new C++ standard upgrades this behavior from "preferred" to mandatory, just like Fortran and C. – Ben Voigt Oct 23 '10 at 22:03
  • @Armen: Also, try explaining the quotient and remainder of (-32768/-1) stored in a 16-bit signed integer type using your quoted specification. The old spec was broken, the new wording is the only one worth anything. – Ben Voigt Oct 23 '10 at 22:07
  • @Ben: I never saw the footnote, thanks for the info. But let's say the old spec "could be better", and not "was broken" because implementation-defined makes their wording not contradictive... convenient :) – Armen Tsirunyan Oct 23 '10 at 22:09
  • 2
    @Armen: The old spec is broken, but the brokenness is different from the sign issue, and it's easy to miss until you look at the new wording. C++03 didn't have "if the quotient a/b is representable in the type of the result", which causes problems for `INT_MIN / -1` (on two's complement implementations). Under the old spec, `-32768 % -1` might have to evaluate to `-65536` (which also isn't in range of the 16-bit type, yuck!) in order for the identity to hold. – Ben Voigt Oct 23 '10 at 23:26
  • 1
    re "However whether or not the remainder is negative is implementation-defined.", C++11 guarantees that integer division rounds towards 0. – Cheers and hth. - Alf Jun 26 '14 at 12:35
  • Note: corner case problems: 1) `mod_rev2(a, INT_MIN)` --> infinite recursion. 2) `mod_rev2(INT_MIN, some_negative_int)` as `-INT_MIN` may lead to undefined behavior. – chux - Reinstate Monica Sep 16 '15 at 19:03
  • I corrected an error in the code for `b<0` (the previous version computed `mod(-a,-b)` rather than `mod(a,-b)`). I'll leave it up to the OP to decide what to do about `b == INT_MIN`. –  Jul 18 '16 at 00:19
  • The expression a % b is undefined when b is not positive. It should be treated like division by zero. – Jive Dadson Dec 17 '16 at 05:26
  • The old declared wrong answer distracts reading. High quality answers just shows the correct answer, don't append it in edits leaving rotten bits. I will upvote when the answer will be cleaned. – ceztko Nov 06 '19 at 21:54
  • The deregistered user @user1084944 changed the code to calculate mod(a,-b) in case of b negative without proper explanation. I restored the previous version. – ceztko Nov 07 '19 at 01:32
  • About the change from @user1084944, I thought more about it: the result of the subtraction of the *remainder* from the *divisor* can be subtracted from the *dividend* so it will be *floor* of the actual division. Let's take for example: mod(13, -8). If it's `mod(a, -b)` -> 5, 13 - 5 = 8 -> 8/-8 = -1. But -1 is the *ceiling* of 13.0 / -8. If it's `mod(-a, -b)` -> 3, 13 - 3 = 10 -> 10 / -8 it's rational so it can't be. If we take `-mod(-a, -b)` -> -3, 13 -(-3) = 16 -> 16 / -8 = -2 and -2 is exactly the *floor* of 13.0 / -8 . I am changing the code accordingly. – ceztko Nov 08 '19 at 21:17
  • Not a proof of correctness but also searching !google "13 mod -8" and the result is -3. – ceztko Nov 08 '19 at 21:21
16

Here is a C function that handles positive OR negative integer OR fractional values for BOTH OPERANDS

#include <math.h>
float mod(float a, float N) {return a - N*floor(a/N);} //return in range [0, N)

This is surely the most elegant solution from a mathematical standpoint. However, I'm not sure if it is robust in handling integers. Sometimes floating point errors creep in when converting int -> fp -> int.

I am using this code for non-int s, and a separate function for int.

NOTE: need to trap N = 0!

Tester code:

#include <math.h>
#include <stdio.h>

float mod(float a, float N)
{
    float ret = a - N * floor (a / N);

    printf("%f.1 mod %f.1 = %f.1 \n", a, N, ret);

    return ret;
}

int main (char* argc, char** argv)
{
    printf ("fmodf(-10.2, 2.0) = %f.1  == FAIL! \n\n", fmodf(-10.2, 2.0));

    float x;
    x = mod(10.2f, 2.0f);
    x = mod(10.2f, -2.0f);
    x = mod(-10.2f, 2.0f);
    x = mod(-10.2f, -2.0f);

    return 0;
}

(Note: You can compile and run it straight out of CodePad: http://codepad.org/UOgEqAMA)

Output:

fmodf(-10.2, 2.0) = -0.20 == FAIL!

10.2 mod 2.0 = 0.2
10.2 mod -2.0 = -1.8
-10.2 mod 2.0 = 1.8
-10.2 mod -2.0 = -0.2

Mathieu
  • 8,840
  • 7
  • 32
  • 45
P i
  • 29,020
  • 36
  • 159
  • 267
  • Unfortunately, this does not work with integers. They would need to be converted to floating point before the division to allow you to use `floor()`. Also, you may loose precision when you convert to float: Try `(float)1000000001/3`, you'll be surprised at the results! – cmaster - reinstate monica Nov 08 '19 at 21:53
  • This works well, I was looking for a replacement for ill-advised usages of `fmod()` with negative `a` parameters. – Kingsley Apr 12 '22 at 00:00
9

I have just noticed that Bjarne Stroustrup labels % as the remainder operator, not the modulo operator.

I would bet that this is its formal name in the ANSI C & C++ specifications, and that abuse of terminology has crept in. Does anyone know this for a fact?

But if this is the case then C's fmodf() function (and probably others) are very misleading. they should be labelled fremf(), etc

efotinis
  • 14,565
  • 6
  • 31
  • 36
P i
  • 29,020
  • 36
  • 159
  • 267
  • 1
    The C11 standard (or the final [public draft](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf) to be exact) mentions "modulo" six times, but only in relation to the representation of various types. Not once does it mention "modulo" in relation to the *remainder* operator (`%`). – Nisse Engström Aug 03 '17 at 21:54
9

The simplest general function to find the positive modulo would be this- It would work on both positive and negative values of x.

int modulo(int x,int N){
    return (x % N + N) %N;
}
Udayraj Deshmukh
  • 1,814
  • 1
  • 14
  • 22
6

For integers this is simple. Just do

(((x < 0) ? ((x % N) + N) : x) % N)

where I am supposing that N is positive and representable in the type of x. Your favorite compiler should be able to optimize this out, such that it ends up in just one mod operation in assembler.

sam hocevar
  • 11,853
  • 5
  • 49
  • 68
Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
  • 3
    Doesn't work: for `int x=-9001; unsigned int N=2000;` it gives 2295, not 999. – Hubert Kario Jan 29 '12 at 01:33
  • 1
    @HubertKario Maybe check again? There is no way that something modulo 2000 gives 2295, you must have made a mistake. – sam hocevar Nov 28 '12 at 15:41
  • 2
    @SamHocevar: I think the problem here is the weird C integer promotion rules. signed promote to unsigned and promoting a negative signed integer value to unsigned invokes undefined behavior in C. – datenwolf Aug 23 '14 at 11:06
  • 2
    I believe a much simpler (and more efficient) form would be: `(x < 0) ? (x % N + N) : (x % N)`. – Chris Nolet Dec 08 '16 at 09:53
4

Here's a new answer to an old question, based on this Microsoft Research paper and references therein.

Note that from C11 and C++11 onwards, the semantics of div has become truncation towards zero (see [expr.mul]/4). Furthermore, for D divided by d, C++11 guarantees the following about the quotient qT and remainder rT

auto const qT = D / d;
auto const rT = D % d;
assert(D == d * qT + rT);
assert(abs(rT) < abs(d));
assert(signum(rT) == signum(D) || rT == 0);

where signum maps to -1, 0, +1, depending on whether its argument is <, ==, > than 0 (see this Q&A for source code).

With truncated division, the sign of the remainder is equal to the sign of the dividend D, i.e. -1 % 8 == -1. C++11 also provides a std::div function that returns a struct with members quot and rem according to truncated division.

There are other definitions possible, e.g. so-called floored division can be defined in terms of the builtin truncated division

auto const I = signum(rT) == -signum(d) ? 1 : 0;
auto const qF = qT - I;
auto const rF = rT + I * d;
assert(D == d * qF + rF);
assert(abs(rF) < abs(d));
assert(signum(rF) == signum(d));

With floored division, the sign of the remainder is equal to the sign of the divisor d. In languages such as Haskell and Oberon, there are builtin operators for floored division. In C++, you'd need to write a function using the above definitions.

Yet another way is Euclidean division, which can also be defined in terms of the builtin truncated division

auto const I = rT >= 0 ? 0 : (d > 0 ? 1 : -1);
auto const qE = qT - I;
auto const rE = rT + I * d;
assert(D == d * qE + rE);
assert(abs(rE) < abs(d));
assert(signum(rE) >= 0);

With Euclidean division, the sign of the remainder is always non-negative.

TemplateRex
  • 69,038
  • 19
  • 164
  • 304
  • `assert(signum(rT) == signum(D));` can definitely fail. Correct statement: `signum(rT)` is a member of the set { `0`, `signum(D)` }, or as an assert `assert(rT == 0 || signum(rT) == signum(D));` – Ben Voigt Jan 11 '21 at 18:44
  • @BenVoigt can you give a counterexample that would fire the assert? – TemplateRex Jan 12 '21 at 10:30
  • Counterexample: `D = 10` and `d = 5` – Ben Voigt Jan 12 '21 at 15:03
  • Final bold statement in your answer is also wrong, should be "non-negative" rather than "positive" – Ben Voigt Jan 12 '21 at 15:04
  • @BenVoigt thank you for your suggested edits, I updated the answer. BTW, I wrote this answer using a home-grown library, which already incorporated your suggested edits, but which I forgot to add to this answer. See https://github.com/rhalbersma/xstd/blob/master/include/xstd/cstdlib.hpp – TemplateRex Jan 12 '21 at 16:32
3

The best solution ¹for a mathematician is to use Python.

C++ operator overloading has little to do with it. You can't overload operators for built-in types. What you want is simply a function. Of course you can use C++ templating to implement that function for all relevant types with just 1 piece of code.

The standard C library provides fmod, if I recall the name correctly, for floating point types.

For integers you can define a C++ function template that always returns non-negative remainder (corresponding to Euclidian division) as ...

#include <stdlib.h>  // abs

template< class Integer >
auto mod( Integer a, Integer b )
    -> Integer
{
    Integer const r = a%b;
    return (r < 0? r + abs( b ) : r);
}

... and just write mod(a, b) instead of a%b.

Here the type Integer needs to be a signed integer type.

If you want the common math behavior where the sign of the remainder is the same as the sign of the divisor, then you can do e.g.

template< class Integer >
auto floor_div( Integer const a, Integer const b )
    -> Integer
{
    bool const a_is_negative = (a < 0);
    bool const b_is_negative = (b < 0);
    bool const change_sign  = (a_is_negative != b_is_negative);

    Integer const abs_b         = abs( b );
    Integer const abs_a_plus    = abs( a ) + (change_sign? abs_b - 1 : 0);

    Integer const quot = abs_a_plus / abs_b;
    return (change_sign? -quot : quot);
}

template< class Integer >
auto floor_mod( Integer const a, Integer const b )
    -> Integer
{ return a - b*floor_div( a, b ); }

… with the same constraint on Integer, that it's a signed type.


¹ Because Python's integer division rounds towards negative infinity.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • your code seems to have the same bug as mine had before my edit. What if b is negative? :) – Armen Tsirunyan Oct 23 '10 at 09:57
  • 1
    @Armen: thanks! but I'm too lazy to edit for just that... :-) – Cheers and hth. - Alf Oct 23 '10 at 10:36
  • @ArmenTsirunyan: the `r` result has to make `a` = `r + b*(a/b)` true. no matter how the integer division is implemented the `b*something` is a multiple of `b`. this makes `r` a valid modulo result even if negative. you can add abs(`b`) to it and it will still be a valid modulo result. – Cheers and hth. - Alf Jun 26 '14 at 12:42
  • 2
    @downvoters: This answer is still correct, while the selected "solution" now contains incorrect commentary due to new guarantees in C++11. It's pretty darn ironic to downvote an answer that's still correct. With no reason given one has to assume that at least 2 associative persons, with almost absolute degree of ignorance, read this question's commentary and knee-jerk-associatively downvoted. Please do explain your downvotes. – Cheers and hth. - Alf Aug 15 '15 at 11:41
  • 1
    The mathematically desired result is for the remainder to be zero or to have the same sign as the divisor (denominator). If the divisor is negative, then the remainder should be zero or negative. The C / C++ implementation results in the remainder being zero or having the same sign as the dividend (numerator). – rcgldr Jul 17 '16 at 23:45
  • @rcgldr: The accepted solution returns non-negative remainder for the case of negative divisor. And so does this answer, because the OP didn't specify a different result in this case, except that this answer produces that result with correct type using a C++ template, which the OP asked for. For the extra requirement, if it is one, one can change `r < 0? r + abs( b ) : r` to `(r == 0? 0 : (r < 0) != (b <0)? r + b : r)`; it can possibly be simplified, not sure. – Cheers and hth. - Alf Jul 18 '16 at 00:24
  • @Cheersandhth.-Alf - Take a look at [wiki modulo](http://en.wikipedia.org/wiki/Modulo_operation). The original release of APL got it wrong, but this was corrected back in the 1960's. Classic languages like Cobol and Fortran and current languages like Matlab and Python have a correct implementation of modulo (some also include a remainder function that works like C / C++). – rcgldr Jul 18 '16 at 01:45
  • @rcgldr: However I'm not sure that Fortran has the math semantics, because C++ got the current (post C++11) rounding rule, rounding towards 0, from Fortran. – Cheers and hth. - Alf Jul 18 '16 at 02:18
  • @Cheersandhth.-Alf - For Fortran, modulo() is different than mod(). Look at the wiki article again. I don't know why C++ chose to use mod() instead of modulo(). I'll delete this comment later – rcgldr Jul 18 '16 at 03:47
2

I believe another solution to this problem would be use to variables of type long instead of int.

I was just working on some code where the % operator was returning a negative value which caused some issues (for generating uniform random variables on [0,1] you don't really want negative numbers :) ), but after switching the variables to type long, everything was running smoothly and the results matched the ones I was getting when running the same code in python (important for me as I wanted to be able to generate the same "random" numbers across several platforms.

david
  • 580
  • 4
  • 12
2

Oh, I hate % design for this too....

You may convert dividend to unsigned in a way like:

unsigned int offset = (-INT_MIN) - (-INT_MIN)%divider

result = (offset + dividend) % divider

where offset is closest to (-INT_MIN) multiple of module, so adding and subtracting it will not change modulo. Note that it have unsigned type and result will be integer. Unfortunately it cannot correctly convert values INT_MIN...(-offset-1) as they cause arifmetic overflow. But this method have advandage of only single additional arithmetic per operation (and no conditionals) when working with constant divider, so it is usable in DSP-like applications.

There's special case, where divider is 2N (integer power of two), for which modulo can be calculated using simple arithmetic and bitwise logic as

dividend&(divider-1)

for example

x mod 2 = x & 1
x mod 4 = x & 3
x mod 8 = x & 7
x mod 16 = x & 15

More common and less tricky way is to get modulo using this function (works only with positive divider):

int mod(int x, int y) {
    int r = x%y;
    return r<0?r+y:r;
}

This just correct result if it is negative.

Also you may trick:

(p%q + q)%q

It is very short but use two %-s which are commonly slow.

Vovanium
  • 3,798
  • 17
  • 23
2

For a solution that uses no branches and only 1 mod, you can do the following

// Works for other sizes too,
// assuming you change 63 to the appropriate value
int64_t mod(int64_t x, int64_t div) {
  return (x % div) + (((x >> 63) ^ (div >> 63)) & div);
}
Kyle Butt
  • 9,340
  • 3
  • 22
  • 15
1
/* Warning: macro mod evaluates its arguments' side effects multiple times. */
#define mod(r,m) (((r) % (m)) + ((r)<0)?(m):0)

... or just get used to getting any representative for the equivalence class.

Eric Towers
  • 4,175
  • 1
  • 15
  • 17
  • 2
    "Get used to getting any representative for the equivalence class"?! That's nonsense. If you wanted that you could just use the original "representative" `r`. The `%` operator has nothing to do with equivalence classes. It's the remainder operator and the remainder is well defined algebraically to be nonnegative and less than the divisor. Sadly C defined it the wrong way. Still, +1 for having one of the best answers. – R.. GitHub STOP HELPING ICE Oct 23 '10 at 19:58
0

Example template for C++

template< class T >
T mod( T a, T b )
{
    T const r = a%b;
    return ((r!=0)&&((r^b)<0) ? r + b : r);
}

With this template, the returned remainder will be zero or have the same sign as the divisor (denominator) (the equivalent of rounding towards negative infinity), instead of the C++ behavior of the remainder being zero or having the same sign as the dividend (numerator) (the equivalent of rounding towards zero).

rcgldr
  • 27,407
  • 3
  • 36
  • 61
-1
define  MOD(a, b)       ((((a)%(b))+(b))%(b))
Blazemonger
  • 90,923
  • 26
  • 142
  • 180
lkw
  • 7
  • 1
  • This works but defining it as a macro like this is ugly as hell. Here's a templated version: http://stackoverflow.com/questions/2581594/how-do-i-do-modulus-in-c/2581867#2581867 – leetNightshade Apr 06 '15 at 19:54
-1
unsigned mod(int a, unsigned b) {
    return (a >= 0 ? a % b : b - (-a) % b);
}
Neuer
  • 33
  • 2
-1

This solution (for use when mod is positive) avoids taking negative divide or remainder operations all together:

int core_modulus(int val, int mod)
{
    if(val>=0)
        return val % mod;
    else
        return val + mod * ((mod - val - 1)/mod);
}
Robotbugs
  • 4,307
  • 3
  • 22
  • 30
-2

I would do:

((-1)+8) % 8 

This adds the latter number to the first before doing the modulo giving 7 as desired. This should work for any number down to -8. For -9 add 2*8.