如何从 bash 中的 mod 获得结果的正号

How to get positive sign for result from mod in bash

当在 bash 中天真地使用 mod 命令时,残差对于负分子得到错误的符号(在我看来):

如果我写:

for i in {-5..5}; do echo $(( $i % 3 )) ; done

我得到输出(作为一行)

-2 -1 0 -2 -1 0 1 2 0 1 2

我如何实现 "correct" 行为

1 2 0 1 2 0 1 2 0 1 2

Add 3然后Mod 3到第一组结果:

$ for i in {-5..5}; do printf "%d " $(( (($i % 3) + 3) % 3 )) ; done
1 2 0 1 2 0 1 2 0 1 2

如果您知道最大范围,则可以在第一次模运算之前添加足够大的 3 倍数以使所有数字为正数。

$ for i in {-5..5}; do printf "%d " $(( ($i + 3000000) % 3 )) ; done

但是,第一种方法更简洁、更通用。

最后,为了好玩:

positive_mod() {
  local dividend=
  local divisor=
  printf "%d" $(( (($dividend % $divisor) + $divisor) % $divisor ))
}

for i in {-5..5}; do
  printf "%d " $(positive_mod $i 3)
done

根据 wikipedia 允许使用负号。

[The result of a mod n] this still leaves a sign ambiguity if the remainder is nonzero: two possible choices for the remainder occur, one negative and the other positive, and two possible choices for the quotient occur. Usually, in number theory, the positive remainder is always chosen, but programming languages choose depending on the language and the signs of a or n.

所以这取决于编程语言来定义它。由于 bash 显然已经选择了 "negative remainder" 方式,您可能会逃脱到例如像这样的 perl:

for i in {-5..5}; do perl -le "print $i%3"; done

This is at the cost of launching the Perl interpreter individually for each integer.

确实如此!由于 OP 似乎关心正确的数学,您可以考虑切换到 python 之类的东西并进行循环和其中的所有操作。

我知道这是一个老问题,但与其循环直到结果为正或启动 perl 或 python,不如考虑以下问题:

for i in {-5..5}; do echo $(( (($i % 3) + 3) % 3)) ; done

这将产生 OP 所需的输出。

这是可行的,因为第一次取模会将结果带入-3到3的范围内,加上3,导致结果在0到6的范围内,然后我们可以再次执行取模(加3没有效果关于这个)。

总的来说:mod = ((a % b) + b) % b