Newbie question: modulo operator with negative operand, bug or feature?


 
Thread Tools Search this Thread
Top Forums Shell Programming and Scripting Newbie question: modulo operator with negative operand, bug or feature?
# 8  
Old 08-11-2015
Quote:
Originally Posted by Scrutinizer
Aia, could you elaborate on why that should render a different outcome ?

In awk:
Code:
awk 'BEGIN {print (-2)%5, -2%5}'
-2 -2

(-2)%5 behaves in what it is called in the Perl documentation as "native C arithmetic" integer arithmetic (as provided by your C compiler) (Almost at the end of the page)
Some more about C affair with modulus.

-2%5 uses the Perl's implementation of how modulus should behave when dealing with negative numbers in Arithmetic.

A relevant discussion about it in one Perl forum

Last edited by Aia; 08-11-2015 at 02:39 PM..
This User Gave Thanks to Aia For This Post:
# 9  
Old 08-11-2015
Hi.

Somewhat extensively for the perl situation:
Quote:
Binary "%" is the modulo operator, which computes the division remainder of its first argument with respect to its second argument. Given integer operands $m and $n : If $n is positive, then $m % $n is $m minus the largest multiple of $n less than or equal to $m . If $n is negative, then $m % $n is $m minus the smallest multiple of $n that is not less than $m (that is, the result will be less than or equal to zero). If the operands $m and $n are floating point values and the absolute value of $n (that is abs($n)) is less than (UV_MAX + 1) , only the integer portion of $m and $n will be used in the operation (Note: here UV_MAX means the maximum of the unsigned integer type). If the absolute value of the right operand (abs($n)) is greater than or equal to (UV_MAX + 1) , "%" computes the floating-point remainder $r in the equation ($r = $m - $i*$n) where $i is a certain integer that makes $r have the same sign as the right operand $n (not as the left operand $m like C function fmod() ) and the absolute value less than that of $n . Note that when use integer is in scope, "%" gives you direct access to the modulo operator as implemented by your C compiler. This operator is not as well defined for negative operands, but it will execute faster.
perlop - perldoc.perl.org

As pointed to from the table of how signs are propagated to results of integer modulo expressions in many programming languages: https://en.wikipedia.org/wiki/Modulo...dulo_operation

Best wishes ... cheers, drl
These 2 Users Gave Thanks to drl For This Post:
# 10  
Old 08-12-2015
Quote:
Originally Posted by jim mcnamara
Code:
echo "(9-7) % 5 = $(( $(( 9 - 7 )) % 5 )) (should be 2)."
# and
echo "(9-7) % 5 = $(( ( 9 - 7 ) % 5 )) (should be 2)."

Note the spaces.

Both work in bash. /bin/sh does not have to always equal bash, it should a modern POSIX shell. I do not know how /bin/sh evaluates on busybox.
Thanks Jim, I tried that and it made no difference:

Code:
echo "The result of A % B should be an integer in the range 0 to B-1, let's test it ..."
echo "(9-7) % 5 = $(( $(( 9 - 7 )) % 5 )) (should be 2)."
echo "(7-9) % 5 = $(( $(( 7 - 9 )) % 5 )) (should be 3)."

Output:

Code:
The result of A % B should be an integer in the range 0 to B-1, let's test it ...
(9-7) % 5 = 2 (should be 2).
(7-9) % 5 = -2 (should be 3).

# 11  
Old 08-12-2015
No spaces are required in an arithmetic evaluation. Spaces are sometimes required when you are doing command substitution when the command being executed by the command substitution starts with a subshell because the $(( could be the start of an arithmetic evaluation or could be the start of a command substitution. If it is intended to be a command substitution starting with a subshell, you may need to have a space between the two opening parentheses to avoid an ambiguity in the shell's grammar.

The following:
Code:
echo "(9-7) % 5 = $(($((9-7))%5)) (should be 2)."

should always work, but:
Code:
echo "$((echo a;echo b)|(wc -l;echo done))"

might or might not work. To make it work reliably, you need a space as shown below:
Code:
var=$( (echo a;echo b)|(wc -l;echo done))

According to the standards, shell script writers should ALWAYS put a space between the parentheses when it is intended to be a command substitution starting with a subshell.
This User Gave Thanks to Don Cragun For This Post:
# 12  
Old 08-12-2015
Thanks drl,

The Perl document says:

Quote:
If $n is positive, then $m % $n is $m minus the largest multiple of $n less than or equal to $m.
which covers this case and the result should be positive or "matching the divisor". As you point out, the Wikipedia table shows BASH gives the same sign as the dividend and ASH seems to be the same.

My application was for a circular counter: given a value m, in the range 0..(size-1), the next entry is next=$(( ($m+1) % $size)) while the previous should be prev=$(( ($m-1) % $size) but that gives -1 for $m=0. The workaround is to use prev=$(( ($m+$size-1) % $size) which should work on any shell.

Thanks for all the detailed replies, I've picked up quite a bit on the syntax from this thread as well as resolving the question.
This User Gave Thanks to FleetFoot For This Post:
Login or Register to Ask a Question

Previous Thread | Next Thread

8 More Discussions You Might Find Interesting

1. What is on Your Mind?

Bug Reporting and Feature Request Tracking on GitHub

Dear All, I created a "new public repo" on GitHub (without the code for now but will post the code there as needed if anyone wants to fix a bug) You can report any forum bugs and report issues in the GitHub "Issues Tab" for this repo here: https://github.com/unixneo/unix.com.bugtracker ... (0 Replies)
Discussion started by: Neo
0 Replies

2. Shell Programming and Scripting

Assignment operator without operand

Does anyone know how this line in bash works? local gotbase= force= nicelevel corelimit local pid base= user= nice= bg= pid_file= local cgroup= These lines are part of the daemon function inside the "functions" file at /etc/init.d in RH. (3 Replies)
Discussion started by: Rameshck
3 Replies

3. Shell Programming and Scripting

Modulo calculation in shell script

hi i am writing a progrm to print the even numbers and the code which i am following is as follows #!/usr/bin/bash echo "enter a number a" read a if then echo "the number is even" else echo "the number is odd" fi ~ what is the mistake i am doing ...please tell me (3 Replies)
Discussion started by: harjinder
3 Replies

4. Shell Programming and Scripting

OR operator syntax question in AWK script

Hi guys, I confused about syntax used in OR script as follow: I have this sample file separated by "|" containing: January|Month No. 1 February|Month No. 2 March|Month No. 3 April|Month No. 4 May|Month No. 5 June|Month No. 6 July|Month No. 7 August|Month No. 8 September|Month No. 9... (11 Replies)
Discussion started by: cgkmal
11 Replies

5. Shell Programming and Scripting

perl newbie . &&..programming newbie (question 2)

Hello everyone, I am having to do a lot of perl scripting these days and I am learning a lot. I have this problem I want to move files from a folder and all its sub folders to one parent folder, they are all .gz files.. there is folder1\folder2\*.gz and there are about 50 folders... (1 Reply)
Discussion started by: xytiz
1 Replies

6. UNIX for Dummies Questions & Answers

UNIX newbie NEWBIE question!

Hello everyone, Just started UNIX today! In our school we use solaris. I just want to know how do I setup Solaris 10 not the GUI one, the one where you have to type the commands like ECHO, ls, pwd, etc... I have windows xp and I also have vmware. I hope I am not missing anything! :p (4 Replies)
Discussion started by: Hanamachi
4 Replies

7. Shell Programming and Scripting

syntax error: `-a' unexpected operator/operand in IF

When i tyr this, it gives me a syntax error...i tried removing quotes,removing spaces,replacing -eq with '='.. Can somebody suggest that is the problem? if ]; then (4 Replies)
Discussion started by: dba.admin2008
4 Replies

8. UNIX for Dummies Questions & Answers

Operator question

I need to find out if a variable contains a certain text string, then do something about it. Here is what I mean, but I don't know how to get a "contains" operator # We have volumes called: # /Volumes/BackupsA_K # /Volumes/BackupsL_Z # /Volumes/Backups_Admin # (could be more, etc)... (5 Replies)
Discussion started by: TheCrunge
5 Replies
Login or Register to Ask a Question