When naively using the mod command in bash the residual gets the wrong sign (in my opinion) for negative numerators:
If i write:
for i in {-5..5}; do echo $(( $i % 3 )) ; done
i get the output (as a row)
-2 -1 0 -2 -1 0 1 2 0 1 2
How do i achieve the "correct" behavior
1 2 0 1 2 0 1 2 0 1 2
$1 means an input argument and -z means non-defined or empty. You're testing whether an input argument to the script was defined when running the script. Follow this answer to receive notifications.
Is modulus always positive? The answer is “Yes”. Reason: The value of modulus of any number is always positive.
So as far as I can tell, %% doesn't have any special meaning in a bash function name. It would be just like using XX instead. This is despite the definition of a name in the manpage: name A word consisting only of alphanumeric characters and under- scores, and beginning with an alphabetic character or an under- score.
To use modulo in the shell, we have to utilize the “expr” command to evaluate its value. So, we have consecutively added three “expr” commands to find out the modulo of two integer values each time by using the “%” operator between them and got three remainder values.
I know it's an old question, but rather than loop until the result is positive or launch perl or python consider the following:
for i in {-5..5}; do echo $(( (($i % 3) + 3) % 3)) ; done
this will result in the OP's desired output.
This works because the first modulo will bring the result into the range -3 to 3, adding 3, causes the result to be in the range 0 to 6, we can then perform modulo again (adding 3 has no effect on this).
in general: mod = ((a % b) + b) % b
Add 3
and then Mod 3
to the first set of results:
$ for i in {-5..5}; do printf "%d " $(( (($i % 3) + 3) % 3 )) ; done
1 2 0 1 2 0 1 2 0 1 2
If you know the maximum range, you can just add a significantly large enough multiple of 3 to make all numbers positive before the first modulo operation.
$ for i in {-5..5}; do printf "%d " $(( ($i + 3000000) % 3 )) ; done
However, the first approach is cleaner and more universal.
Lastly, for fun:
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
According to wikipedia negative signs are allowed.
[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.
So it's up to the programming language to define this. As bash has obviously gone for the "negative remainder" way you might escape to e.g. perl like this:
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.
Indeed! Since the OP seem to care about correct math, you might consider switching to something like python
and do the looping and everything in there.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With