Reputation: 88037
I'm brand new to Erlang. How do you do modulo (get the remainder of a division)? It's % in most C-like languages, but that designates a comment in Erlang.
Several people answered with rem, which in most cases is fine. But I'm revisiting this because now I need to use negative numbers and rem gives you the remainder of a division, which is not the same as modulo for negative numbers.
Upvotes: 52
Views: 43699
Reputation: 1387
I used the following in elixir:
defp mod(x,y) when x > 0, do: rem(x, y);
defp mod(x,y) when x < 0, do: rem(x, y) + y;
defp mod(0,_y), do: 0
Upvotes: 10
Reputation: 4046
In Erlang, 5 rem 3.
gives 2
, and -5 rem 3.
gives -2
. If I understand your question, you would want -5 rem 3.
to give 1 instead, since -5 = -2 * 3 + 1.
Does this do what you want?
mod(X,Y) when X > 0 -> X rem Y;
mod(X,Y) when X < 0 -> Y + X rem Y;
mod(0,Y) -> 0.
Upvotes: 45
Reputation: 41
The above Y + X rem Y seems to be wrong: either (Y + X) rem Y or Y + (X rem Y) yield incorrect results. Ex: let Y=3. If X=-4, the first form returns -1, if X=-3 the second form returns 3, none of which is in [0;3[.
I use this instead:
% Returns the positive remainder of the division of X by Y, in [0;Y[.
% In Erlang, -5 rem 3 is -2, whereas this function will return 1,
% since -5 =-2 * 3 + 1.
modulo(X,Y) when X > 0 ->
X rem Y;
modulo(X,Y) when X < 0 ->
K = (-X div Y)+1,
PositiveX = X + K*Y,
PositiveX rem Y;
modulo(0,_Y) ->
0.
Upvotes: 4
Reputation: 31
The accepted answer is wrong.
rem
behaves exactly like the %
operator in modern C. It uses truncated division.
The accepted answer fails for X<0 and Y<0. Consider mod(-5,-3)
:
C: -5 % -3 == -2
rem: -5 rem -3 == -2
Y + X rem Y: -3 + -5 rem -3 == -5 !! wrong !!
The alternative implementations for the modulo operator use floored division and Euclidean division. The results for those are
flooring division: -5 mod -3 == -2
euclidean division: -5 mod -3 == 1
So
Y + X rem Y
doesn't reproduce any modulo operator for X < 0 and Y < 0.
And rem
works as expected -- it's using truncated division.
Upvotes: 2
Reputation: 1260
mod(A, B) when A > 0 -> A rem B;
mod(A, B) when A < 0 -> mod(A+B, B);
mod(0, _) -> 0.
% console:
3> my:mod(-13, 5).
2
Upvotes: 1
Reputation: 10241
Erlang remainder not works with negative numbers, so you have to write your own function for negative parameters.
Upvotes: 2
Reputation: 339786
The erlang modulo operator is rem
Eshell V5.6.4 (abort with ^G)
1> 97 rem 10.
7
Upvotes: 32