PDA

Просмотр полной версии : пара математических скриптов


Ky3bMu4
22.02.2008, 20:02
Вот, для себя и чтоб попрактиковаться в bash`е, написал пару скриптов. Опыта пока мало - просьба сильно не пинать :) .
Первый - работа с комплексной арфиметикой, + - / * , возведение в степень(целую), извлечение корня, привидение в тригонометрическую форму.

#!/bin/bash

pi=$(echo "4*a(1)"|bc -l)

summ() #вычисление суммы
{
re=$(echo "$1+$3"|bc)
im=$(echo "$2+$4"|bc)
}

sub() #разности
{
re=$(echo "$1-$3"|bc)
im=$(echo "$2-$4"|bc)
}

mult() #умножение
{
re=$(echo "$1*$3-$2*$4"|bc)
im=$(echo "$3*$2+$1*$4"|bc)
}

div() #деление
{
del=$(echo "$3^2+$4^2"|bc)
re=$(echo "$1*$3+$2*$4"|bc)
im=$(echo "$3*$2-$1*$4"|bc)
}

trig() #получение тригонометрической формы
{
r2=$(echo "$1^2+$2^2"|bc)
case "$1" in
0) a=$(echo "0.5+(($2/sqrt($2^2)-1)/-2)"|bc) ;;
*) a=$(echo "a($2/$1)/$pi"|bc -l)
esac

}

use()
{
echo "Use: $0 re1 im1 [+|-|/|x] re2 im2"
echo " $0 re 1 im1 [sqrt|xx] st"
}

if [ $# = 5 ]; then #передали 5 параетров, значит + - / x

case "$3" in
"+") summ $1 $2 $4 $5 ;;
"-") sub $1 $2 $4 $5 ;;
"x") mult $1 $2 $4 $5 ;;
"/") div $1 $2 $4 $5 ;;
*) use
esac

if [ "$3" = "/" ]; then
echo "Result: ($re/$del;$im/$del)"
else
echo "Result: ($re;$im)"
fi

elif [ $# = 4 ]; then
case "$3" in
"xx") #возводим в степень
i=1
re1=$1
im1=$2
until [ $i = $4 ]; do #сначала в обычном виде
mult $re1 $im1 $1 $2
re1=$re
im1=$im
let "i+=1"
done
echo "Result: ($re;$im)"
trig $re $im
echo "Result num in trig form: sqrt($r2)(cos($a pi)+i*sin($a pi))"
trig $1 $2
echo "Original num in trig form: sqrt($r2)(cos($a pi)+i*sin($a pi))" #теперь выводим в тригонометрическом
;;

"sqrt") #извлекаем корень степени $4
trig $1 $2
i=0
echo "Results:"
until [ $i = $4 ]; do #корень n-степени - n корней
a2=$(echo "($a+2*$i)/$4"|bc -l)
echo "sqrt($r2)^1/$4(cos($a2 pi)+i*sin($a2 pi))"
let "i+=1"
done
;;
*) use
esac

else
use
fi



Второй скрипт - рекурсивное вычисление определителя матрицы. Т.к. bash не поддерживает двумерных массивов, то пришлось использовать одномерные. Но вот проблема - как в функцию в качестве параметра передать массив где могут быть пробелы(к примеру: "1 0 0 1")? При попытке передать такой массив передаётся только первый символ. Так что пока скрип считает только 2х2 и 3х3(но алгоритм всё равно рекурсивный и расчитан на безразмерную матрицу)

#!/bin/bash

declare -a mo
declare -a mn

use(){
echo "Use: $0 [sizeof matrix]"
}

#in:
#$1 - размерность матрицы
#$2 - номер эл-мента первой строки который(он же номер столбца который вычеркиваем)
#out:
#$mn - минор
getnew(){ #получение минора
start=$(($1+1)) #всегда считаем по 1 строке поэтому вычеркиваем первые $1 эл-ментов
size=$(echo "($1+1)^2"|bc) #кол-во эл-ментов матрицы
end=$(($size+1))
i=$start
n=0
until [ $i = $end ]; do #проходим по всем эл-ментам матрицы
nr=$(echo "$i-($i%$start)+$2"|bc)
if [ $i != $nr ]; then
mn[$n]=${mo[$i]}
let "n+=1"
fi
let "i+=1"
done
}

#in:
#$1 - размерность матрицы
#out:
#$det - определитель матрицы $1
getdet(){
case "$1" in
1) det=$(echo "${mn[0]}*${mn[3]}-${mn[1]}*${mn[2]}"|bc) ;; # с случаем 2х2 всё ясно
*)
s=0
tmpdet=0
until [ $s = $(($1+1)) ]; do #иначе проходим по 1 строке и считаем $1 определителей
getnew $1 $s
new1=$(($1-1)) #размерность уменьшается на 1
getdet $new1
tmpdet=$(echo "(-1^($s%2))*$det*${mo[$s]}+$tmpdet"|bc)
let "s+=1"
done
det=$tmpdet
esac

}

if [ $# = 1 ]; then
echo "Please, enter the matrix m[0][0] m[0][1] ... m[1][0] m[1][1] ... m[$1][$1]"
echo "Example: 1 0 0 1"
read -a mo
echo $g
mn=( ${mo[@]} )
getdet $1
echo $det
else
use
fi

nikto
02.03.2008, 20:43
>> Но вот проблема - как в функцию в качестве параметра передать массив где могут быть пробелы(к примеру: "1 0 0 1")?

Помоему пробелы надо экранировать.
намример 1\ 0\ 0\ 1
Но я не уверен

Deem3n®
02.03.2008, 22:23
#!/bin/bash
function sekas()
{
array=( "$@" )
for i in array `seq 1 $(( ${#array[@]}-1))`;
do
echo "${array[i]}"
done
}

sekas_parms="0 1 0 1"
sekas ${sekas_parms[@]}


dima@gentoo-nb ~ $ ./1.sh
0
1
0
1