Форум АНТИЧАТ

Форум АНТИЧАТ (https://forum.antichat.xyz/index.php)
-   *nix (https://forum.antichat.xyz/forumdisplay.php?f=43)
-   -   пара математических скриптов (https://forum.antichat.xyz/showthread.php?t=62464)

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



Время: 17:00