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

问题描述 投票:5回答:3

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

如果我写:

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

我得到输出(作为一行)

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

我如何实现“正确”的行为

1 2 0 1 2 0 1 2 0 1 2
bash mod
3个回答
1
投票

我知道这是一个老问题,但不是循环,直到结果为正或启动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


3
投票

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=$1
  local divisor=$2
  printf "%d" $(( (($dividend % $divisor) + $divisor) % $divisor ))
}

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

2
投票

根据wikipedia允许的负面迹象。

[a mod n的结果]如果余数为非零,这仍然会留下符号模糊:剩余部分有两种可能的选择,一种是负的,另一种是正的,并且出现两种可能的商选择。通常,在数论中,总是选择正余数,但编程语言根据语言和a或n的符号选择。

所以由编程语言来定义它。由于bash显然已经走向了“负剩余”的方式,你可能会逃到例如像这样的perl:

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

这是以为每个整数单独启动Perl解释器为代价的。

确实!由于OP似乎关心正确的数学,你可能会考虑切换到像python这样的东西并进行循环以及其中的所有内容。

© www.soinside.com 2019 - 2024. All rights reserved.