bash numeric arithmetic substitution - ghdrako/doc_snipets GitHub Wiki
The shell allows arithmetic expressions to be evaluated, as one of the
- shell expansions or
- by using the (( compound command,
- the let builtin, or
- the -i option to the declare builtin.
shell expansions - double parentheses syntax - arithmetic substitution
A more modern and convenient way to perform arithmetic operations is using the double parentheses syntax. Arithmetic expansion(substitution) allows the evaluation of an arithmetic expression and the substitution of the result. The format for arithmetic expansion is:
$[ expression ] # w starszych wersjach bash przestarzale np. result=$[ 2000+300 ]
$(( expression ))
#add integers a to b and assign to c:
a=5
b=7
c=$((a+b))
# Perform addition
result=$((5 + 3))
echo $result
# Output: 8
# Perform multiplication
result=$((10 * 2))
echo $result
# Output: 20
# Perform arithmetic operation with precedence
result=$((1 + 2 * 3))
echo $result
# Output: 7
# Initialize value
value=0
# Increment value by 1
((value++))
echo $value
# Output: 1
# Decrement value by 1
((value--))
echo $value
# Output: 0
converting any number to decimal
$ echo $((16#1AC))
428
$ echo $((0x1AC))
428
The base is specified as 16# (or 0x) followed immediately by the number to be converted. The result is the decimal value of this hexadecimal number. The same can be done for any base number in order to convert it to decimal. For instance Listing 3.2 shows the conversion of 10101100b to decimal
$ echo $((2#10101100))
172
Aritmetics
$ a=5; a+=2; echo "$a"; unset a
52
$ a=5; let a+=2; echo "$a"; unset a
7
$ declare -i a=5; a+=2; echo "$a"; unset a
7
$ a=5+2; echo "$a"; unset a
5+2
$ declare -i a=5+2; echo "$a"; unset a
7
Most experienced shell scripters prefer to use explicit arithmetic commands (with ((...)) or let) when they want to perform arithmetic. And they don't use declare -i. The same is explicit declaration of an array using declare -a. It is sufficient to write array=(...) insteed.
The exception to this is the associative array, which must be declared explicitly: declare -A myarray
.
declare -i MYVAR #declare variable as integer
declare -i SEE
X=9
Y=3
SEE=X+Y # only this one will be arithmetic
SAW=X+Y # this is just a literal string
SUM=$X+$Y # this is string concatenation
echo "SEE = $SEE"
echo "SAW = $SAW"
echo "SUM = $SUM"
step=$(( step + 1 )) # $((step++)) will return a numeric value — Which the shell will then take as the name of a command to be executed. If step++ evaluated to 3 then the shell would look for a command named 3.
median_loc=$(( len / 2 ))
dist=$(( dist * 4 ))
if (( OTHERVAL * 10 <= VAL / 5 )) ; then ...
EXPR
The expr command evaluates expressions and prints the result. Basic arithmetic using expr
# Perform addition
result=$(expr 5 + 3)
echo $result
# Output: 8
# Perform multiplication (escape the asterisk)
result=$(expr 10 \* 2)
echo $result
# Output: 20
expr 5 + 4
expr "5 + 4"
expr 5+4
expr 5 \* $1
expr 11 % 2
a=$( expr 10 - 3 )
echo $a # 7
let
let evaluates the expression in a manner similar to the double parentheses syntax
# Perform addition
let result=5+3
echo $result
# Output: 8
# Perform multiplication
let result=10*2
echo $result
# Output: 20
# Initialize value
value=0
# Increment value by 1
let value++
echo $value
# Output: 1
# Decrement value by 1
let value--
echo $value
# Output: 0
Floating-point aritmetics
In Bash, expressions like $((1.5 + 2.3))
will throw an error because
Bash does not support floating-point arithmetic natively. Instead, you
must rely on external tools like bc
and awk
.
BC
The shell natively handles only integer arithmetic. For floating-point operations, bc (Basic Calculator)
# Perform division with two decimal places
result=$(echo "scale=2; 5 / 3" | bc)
echo $result
# Output: 1.66
By setting the scale parameter, we can specify the number of decimal places.
echo "12+5" | bc
echo "10^2" | bc
x=`echo "12+5" | bc`
echo $x
#Output:17
pi=`echo "h=10;4*a(1)" | bc -l`
echo $pi
echo "e(3)" | bc -l #exponential^value as output
echo "ibase=2;1111" | bc -l # Convert Decimal to Octal
echo "ibase=2;1111" | bc -l # Convert Binary to Decimal
echo "ibase=2;obase=8;10" | bc -l # Convert Binary to Octal
Convert from decimal to other number systems
$ echo "obase=16; ibase=10; 428" | bc
1AC
The input (ibase)andoutput(obase) bases are specified in advance. Finally the number, in the input base, is provided. All of this is piped to bc which performs the conversion. Note that the default value for bases, both input and output, is 10
, so the command: echo “obase=16; 428” | bc
would have the same effect.
However, the general format (i.e. specifying both input and output bases) can be used to convert any pair of number system.
$ echo "obase=16; ibase=2; 101010" | bc
2A
$ echo "obase=5; ibase=16; C" | bc
22
awk
num1=1.5
num2=2.3
result=$(echo "$num1 $num2" | awk '{print $1 + $2}')
echo "Result using awk: $result"