在 Erlang 中如何使用模运算或余数?

51

我是Erlang的新手。如何执行模运算(获取除法余数)?在大多数类C语言中,它是%,但在Erlang中这表示注释。

许多人都用rem来回答,这在大多数情况下是可以的。但是我正在重新考虑这个问题,因为现在我需要使用负数并且rem给出的是除法余数,而不是负数情况下的模运算结果。


3
取模运算没有一个清晰的定义,对于 C 和 C++ 而言,% 在负数情况下是由实现决定的(遵循 ISO C90 标准)。后续标准则像 Erlang 一样准确定义了它。详细信息请参见 http://en.wikipedia.org/wiki/Modulo_operation。 - Peer Stritzinger
8个回答

44
在Erlang中,5 rem 3.的结果是2-5 rem 3.的结果是-2。如果我理解你的问题,你希望-5 rem 3.的结果是1,因为-5 = -2 * 3 + 1.。这样做是否符合你的要求?
mod(X,Y) when X > 0 -> X rem Y;
mod(X,Y) when X < 0 -> Y + X rem Y;
mod(0,Y) -> 0.

这个会起作用。但是,erlang真的没有任何分布式处理这个的工具吗? - Matt
1
不按照 Erlang 参考手册(http://erlang.org/doc/reference_manual/expressions.html) (第6.12节)。 - grifaton
9
或者:mod(X,Y)->(X rem Y + Y) rem Y。 - Koistinen

32

erlang取模运算符是rem

Eshell V5.6.4  (abort with ^G)
1> 97 rem 10.
7

10

我在 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

1
这就是 Integer.mod/2 的作用。 - Adam Millerchip
这个答案的第二个子句有错误。在x <0且rem(x, y) ==0的情况下,它将无法正常运行,比如-5,5。在这种情况下,第二个子句会返回5而不是0。 - undefined

4
上述的 Y + X rem Y 似乎是错误的:无论是 (Y + X) rem Y 还是 Y + (X rem Y),都会产生错误的结果。例如,让 Y=3。如果 X=-4,则第一种形式返回 -1,如果 X=-3,则第二种形式返回 3,这两个结果都不在 [0;3[ 范围内。
我使用以下方法代替:
% 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.

4

2

被接受的答案是错误的。

rem 的行为与现代 C 中的 % 运算符完全相同。它使用截断除法。

被接受的答案在 X<0 和 Y<0 时会失败。考虑 mod(-5,-3)

C:                     -5 % -3 == -2
rem:                 -5 rem -3 == -2
Y + X rem Y:    -3 + -5 rem -3 == -5 !! wrong !!

取模运算的替代实现使用向下取整除法和欧几里得除法。它们的结果如下:

flooring division:   -5 mod -3 == -2
euclidean division:  -5 mod -3 == 1

所以。
Y + X rem Y

当X < 0且Y < 0时,不会产生任何模运算符。

rem按预期工作 - 它使用截断除法。


2

Erlang的余数函数不能处理负数,因此您需要为负参数编写自己的函数。


1
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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接