пара математических скриптов

Discussion in 'Безопасность и Анонимность' started by Ky3bMu4, 22 Feb 2008.

  1. Ky3bMu4

    Ky3bMu4 Elder - Старейшина

    Joined:
    3 Feb 2007
    Messages:
    487
    Likes Received:
    284
    Reputations:
    42
    Вот, для себя и чтоб попрактиковаться в bash`е, написал пару скриптов. Опыта пока мало - просьба сильно не пинать :) .
    Первый - работа с комплексной арфиметикой, + - / * , возведение в степень(целую), извлечение корня, привидение в тригонометрическую форму.
    Code:
    #!/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(но алгоритм всё равно рекурсивный и расчитан на безразмерную матрицу)
    Code:
    #!/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
    
     
    1 person likes this.
  2. nikto

    nikto Elder - Старейшина

    Joined:
    2 Mar 2008
    Messages:
    39
    Likes Received:
    11
    Reputations:
    4
    >> Но вот проблема - как в функцию в качестве параметра передать массив где могут быть пробелы(к примеру: "1 0 0 1")?

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

    Deem3n® RTFMSDN

    Joined:
    19 Sep 2005
    Messages:
    378
    Likes Received:
    153
    Reputations:
    164
    Code:
    #!/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[@]}
    
    Code:
    dima@gentoo-nb ~ $ ./1.sh
    0
    1
    0
    1
    
     
    #3 Deem3n®, 2 Mar 2008
    Last edited: 2 Mar 2008
    1 person likes this.