среда, 9 февраля 2011 г.

BASH. Матеметика.

Заметки по математическим операциям в bash
Изначально следует отметить, что для математических вычислений используется let.
Поддерживаются следующие операции:
Подготовка
создадим эксперементальный файл.
touch /root/test.sh
и зададим права на исполнение
chmod a+x /root/test.sh

Сложение
nano -w /root/test.sh
#!/bin/bash
VAR1=$1
VAR2=$2

let "VAR3 = VAR1 + VAR2"
echo "VAR1+VAR2= $VAR3"

Claes / # /root/test.sh 277 19
VAR1+VAR2= 296
Кроме того возможно использовать вокращения вида +=
то есть запись вида
VAR1 = VAR1 + VAR2
аналогична
VAR1 += VAR2
Такая запись может упростить чтение кода.

Вычитание
Подправим файлик
nano -w /root/test.sh
#!/bin/bash
VAR1=$1
VAR2=$2

let "VAR3 = VAR1 - VAR2"
echo "VAR1-VAR2= $VAR3"
Claes / # /root/test.sh 123 54
VAR1-VAR2= 69
Claes / # /root/test.sh 54 123
VAR1-VAR2= -69
Аналогично поддерживается сокращенная запись -=

Умножение
Подправим файлик
nano -w /root/test.sh
#!/bin/bash
VAR1=$1
VAR2=$2

let "VAR3 = VAR1 * VAR2"
echo "VAR1*VAR2= $VAR3"
let "VAR3=VAR1*1,25"
echo "VAR1*1,25 = " $VAR3
let "VAR3=VAR1*1,75"
echo "VAR1*1,75 = " $VAR3
let "VAR3=VAR1*2,25"
echo "VAR1*2,25 = " $VAR3
Claes / # /root/test.sh 54 12
VAR1*VAR2= 648
VAR1*1,25 = 54
VAR1*1,75 = 54
VAR1*2,25 = 108
Как видно из приведенного let работает только с целыми частями чисел.

Целочисленное деление
Подправим файлик
nano -w /root/test.sh
#!/bin/bash
VAR1=$1
VAR2=$2

let "VAR3 = VAR1 / VAR2"
echo "VAR1/VAR2= $VAR3"
let "VAR3=VAR1/1,25"
echo "VAR1/1,25 = " $VAR3
let "VAR3=VAR1/1,75"
echo "VAR1/1,75 = " $VAR3
let "VAR3=VAR1/2,25"
echo "VAR1/2,25 = " $VAR3
Claes / # /root/test.sh 54 12
VAR1/VAR2= 4
VAR1/1,25 = 54
VAR1/1,75 = 54
VAR1/2,25 = 27
Как видно по результатам продлема у умножения и деления одна и таже.

Определение остатка от деления
Подправим файлик
nano -w /root/test.sh
#!/bin/bash
VAR1=$1
VAR2=$2

let "VAR3 = VAR1 % VAR2"
echo "VAR1%VAR2= $VAR3"
let "VAR3=VAR1%1,25"
echo "VAR1%1,25 = " $VAR3
let "VAR3=VAR1%1,75"
echo "VAR1%1,75 = " $VAR3
let "VAR3=VAR1%2,25"
echo "VAR1%2,25 = " $VAR3
Результат так же показывает на невозможность оперирования десятичными дробями
Claes / # /root/test.sh 54 12
VAR1%VAR2= 6
VAR1%1,25 = 0
VAR1%1,75 = 0
VAR1%2,25 = 0

Сдвиг числа вправо и влево
nano -w /root/test.sh
#!/bin/bash
VAR1=$1
# Сдвигаемое значение
VAR2=$2
# Кол-во сдвигов

echo " Сдвиг числа влево"
n="0"
while [ "$n" -le "$VAR2" ]
do
VAR3=VAR1
let "VAR3 <<= $n"
echo "$VAR1 <<= $n = " $VAR3
let "n+=1"
done
echo "====================="
echo " Сдвиг числа вправо"
n="0"
while [ "$n" -le "$VAR2" ]
do
VAR3=VAR1
let "VAR3 >>= $n"
echo "$VAR1 >>= $n = " $VAR3
let "n+=1"
done
Результат исполнения:
Claes / # /root/test.sh 54 10
Сдвиг числа влево
54 <<= 0 = 54
54 <<= 1 = 108
54 <<= 2 = 216
54 <<= 3 = 432
54 <<= 4 = 864
54 <<= 5 = 1728
54 <<= 6 = 3456
54 <<= 7 = 6912
54 <<= 8 = 13824
54 <<= 9 = 27648
54 <<= 10 = 55296
=====================
Сдвиг числа вправо
54 >>= 0 = 54
54 >>= 1 = 27
54 >>= 2 = 13
54 >>= 3 = 6
54 >>= 4 = 3
54 >>= 5 = 1
54 >>= 6 = 0
54 >>= 7 = 0
54 >>= 8 = 0
54 >>= 9 = 0
54 >>= 10 = 0

Возведение в степень
nano -w /root/test.sh
#!/bin/bash
VAR1=$1
VAR2=$2

let "VAR3 = VAR1 ** VAR2"
echo "VAR1**VAR2= $VAR3"
let "VAR3=VAR1**1,25"
echo "VAR1**1,25 = " $VAR3
let "VAR3=VAR1**1,75"
echo "VAR1**1,75 = " $VAR3
let "VAR3=VAR1**2,25"
echo "VAR1**2,25 = " $VAR3
Результат так же показыват на невозможность оперирования десятичными дробями
Claes / # /root/test.sh 54 3
VAR1**VAR2= 157464
VAR1**1,25 = 54
VAR1**1,75 = 54
VAR1**2,25 = 2916

Приоритезация вычислений Как и любой порядочный калькулятор let имеет лексический анализатор и разбирая выражения производит вычисления согласно общепринятой последовательности вычислений.
Для демонстрации вычислений правим
nano -w /root/test.sh
#!/bin/bash
let "VAR=2+2*2"
echo "2+2*2 = "$VAR

let "VAR=(2+2)*2"
echo "(2+2)*2 = "$VAR

let "VAR=2+5*8-8/7"
echo "2+5*8-8/7 = "$VAR

let "VAR=(2+5)*8-8/7"
echo "(2+5)*8-8/7 = "$VAR

let "VAR=(2+5)*8-8*2/7"
echo "(2+5)*8-8*2/7 = "$VAR

let "VAR=(2+5)*8-8**2/7"
echo "(2+5)*8-8**2/7 = "$VAR

let "VAR=(2+5)*8-8**2/(7+5)"
echo "(2+5)*8-8**2/(7+5) = "$VAR
Результат вычислений говорить сам за себя.
Claes / # /root/test.sh
2+2*2 = 6
(2+2)*2 = 8
2+5*8-8/7 = 41
(2+5)*8-8/7 = 55
(2+5)*8-8*2/7 = 54
(2+5)*8-8**2/7 = 47
(2+5)*8-8**2/(7+5) = 51

Заключение
Так как let не воспринимает дробные числа для получения результатов вычислений с участием дробных чисел придется поизолятся и сделать дробные числа целыми. Например:
a*0.95 ~~ let "a=(a*95)/100"
Следует обратить внимание на то, что:
приведенно го списка больше чем достаточно. Лично у меня еще не возникало необходимости в бо`льшем количестве математических операций.
Округдение вниз, являющееся последствием целочисленности, я считаю блольше положительным.
Возможность сокращения записи вида a=a+b к виду a+=b также следует отнести к положительным сторонам.

Комментариев нет:

Отправить комментарий