Felhasználói eszközök

Eszközök a webhelyen


st-linux_alapok:fejezetek:bc-gyak

A bc program

A bc egy lebegőpontos számológép:

palferi@lizi:~$ bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
scale=12
1/27+(3^5)
243.037037037037
last-32
211.037037037037
sqrt(134)
11.575836902790
quit

Láthatjuk, hogy a scale a pontosságot állítja be, használhatjuk az alapvető számtani műveleteket, a last a legutolsó eredményt jelenti, az sqrt() pedig a négyzetgyök kiszámítása. A quit paranccsal lépünk ki aprogramból.

Matematikai függvények a bc programban

Ha a bc-t a -l opcióval indítjuk, a matematikai könyvtár betöltődik, és a pontosság 20-as lesz. A matematikai függvények azzal a pontossággal számolják ki az eredményt, amely a meghívásukkor be volt állítva. A matematikai könyvtár a következő függvényeket definiálja:

s(x) Az x (radián) szinusza
c(x) Az x (radián) koszínusza
a(x) Az x arkusz tangense
l(x) Az x természetes logaritmusa
e(x) Az e x-edik hatványa
j(n,x) Az n-ed rendű Bessel fuggvenye x-nek

A π kiszámítása a bc programmal

Számítsuk ki a π szám értékét 20, majd 1000 számjegy pontossággal:

palferi@lizi:~$ bc -l
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
4*a(1)
3.14159265358979323844
scale=1000
4*a(1)
3.141592653589793238462643383279502884197169399375105820974944592307\
81640628620899862803482534211706798214808651328230664709384460955058\
22317253594081284811174502841027019385211055596446229489549303819644\
28810975665933446128475648233786783165271201909145648566923460348610\
45432664821339360726024914127372458700660631558817488152092096282925\
40917153643678925903600113305305488204665213841469519415116094330572\
70365759591953092186117381932611793105118548074462379962749567351885\
75272489122793818301194912983367336244065664308602139494639522473719\
07021798609437027705392171762931767523846748184676694051320005681271\
45263560827785771342757789609173637178721468440901224953430146549585\
37105079227968925892354201995611212902196086403441815981362977477130\
99605187072113499999983729780499510597317328160963185950244594553469\
08302642522308253344685035261931188171010003137838752886587533208381\
42061717766914730359825349042875546873115956286388235378759375195778\
18577805321712268066130019278766111959092164201988
quit

A bc használata szkriptben

Shell szkriptben vagy parancssorból közvetlenül is meghívhatjuk a bc programot az echo parancs és csővezeték segítségével:

palferi@lizi:~$ echo "scale=30; 4*a(1)" | bc -l
3.141592653589793238462643383276
palferi@lizi:~$ echo "scale=30; sqrt(42)+27" | bc
33.480740698407860230965967436087

A time paranccsal meghatározhatjuk a számításra fordított időt. Nagyobb pontosság megadásával meghatározhatjuk gépünk sebességét, összehasonlíthatjuk más gépekével. Vegyük figyelembe viszont, hogy a bc program csak egy processzormagot használ. A következő parancs 5000 tizedesjegy pontossággal határozza meg a π számot, kiírja az erre fordított processzoridőt és processzor fontosabb paramétereit:

palferi@lizi:~$ time echo "scale=5000; 4*a(1)" | bc -l ; cat /proc/cpuinfo | grep -E '(model name|bogomips|MHz)'
3.141592653589793238462643383279502884197169399375105820974944592307\
81640628620899862803482534211706798214808651328230664709384460955058\
...
74351362222477158915049530984448933309634087807693259939780541934144\
73774418426312986080998886874132604720
 
real	0m20.903s
user	0m20.885s
sys	0m0.004s
model name	: Intel(R) Core(TM) i5-3330 CPU @ 3.00GHz
cpu MHz		: 3001.000
bogomips	: 5986.03
model name	: Intel(R) Core(TM) i5-3330 CPU @ 3.00GHz
cpu MHz		: 1600.000
bogomips	: 5986.03
model name	: Intel(R) Core(TM) i5-3330 CPU @ 3.00GHz
cpu MHz		: 1600.000
bogomips	: 5986.03
model name	: Intel(R) Core(TM) i5-3330 CPU @ 3.00GHz
cpu MHz		: 1600.000
bogomips	: 5986.03

Feladat 1. A másodfokú egyenlet megoldása

Írjon szkriptet megy.sc néven ami a másodfokú egyenlet gyökeit keresi meg. Az a, b, c együtthatókat paraméterként adja meg.
A másodfokú egyenlet megoldóképlete: $$x_{1,2} = \frac{ -b \pm \sqrt{b^2 - 4ac} }{ 2a}$$ A $b^2 - 4ac$ kifejezést diszkriminánsnak nevezzük. Határozzuk meg a diszkriminánst:

#!/bin/bash
echo "Az ax^2+bc+c=0 egyenlet megoldása"
A=$1; B=$2; C=$3
DR=`echo "scale=4; $B^2-4*$A*$C" | bc`
echo "Diszkrimináns: $DR"

Amennyiben a diszkrimináns nulla, kiszámítjuk a gyököt (kettős gyök) és kilépünk az exit 0 paranccsal a programból:

if test $DR -eq 0
then
echo "A másodfokú egyenletnek egy valós (kettős) gyöke van:"
X12=`echo "scale=4; -$B/(2*$A)" | bc`
echo $X12
exit 0
fi

A programot olyan paraméterekkel indítva, amelyekkel a diszkrimináns nulla:

palferi@lizi:~$ ./megy.sc 2 4 2
Az ax^2+bc+c=0 egyenlet megoldása
Diszkrimináns: 0
A másodfokú egyenletnek egy valós (kettős) gyöke van:
-1.0000

Amennyiben a diszkrimináns negatív, az egyenletnek nincsenek valós gyökei:

if test $DR -lt 0
then
echo "A másodfokú egyenletnek nincsenek valós gyökei"
exit 0
fi

Minden más esetben:

echo "A másodfokú egyenlet gyökei:"
X1=`echo "scale=4; (-$B+sqrt($DR))/(2*$A)" | bc`
X2=`echo "scale=4; (-$B-sqrt($DR))/(2*$A)" | bc`
echo "X1=$X1"
echo "X2=$X2"

Ne feledjük, hogy a szkript csak egész számokkal működik helyesen és az a együttható nem lehet nulla.

Feladat 2. Fokérték szinusza

Írjon szkriptet fsin.sc néven ami a paraméterébe megadott fokérték szinuszát számítja ki 24 tizedesjegy pontossággal. A program ellenőrizze, hogy csak egy egész szám paramétert kapott és a paraméter nem kisebb mint -360 és nem nagyobb 360.

#!/bin/bash
if [ $# -eq 1 ]
then
P1=`echo $1 | grep -E '^[0-9-]?[0-9]+$'`
    if [ -n "$P1" ]
    then
	if [ $1 -gt -360 ] && [ $1 -lt 360 ]
	then
	SIN=`echo "scale=24; s(((4*a(1))/180)*$1)" | bc -l`
	echo "sin($1)=$SIN"
	else
	echo "A paraméter étréke nem -360 és 360 között van."
	fi
     else
    echo "A paraméter nem egész szám"
    fi
else
echo "Egy paramétert kell megadni!"
fi

A programban először azt ellenőrizzük, hogy egy paramétert adtunk meg, majd reguláris kifejezéssel, hogy egész számot. A P1 változó értéke csak akkor lesz nem nulla hosszúságú karakterlánc, ha egész számot adunk meg paraméterként. Emlékezzünk vissza a reguláris kifejezéseknél tárgyaltuk, hogy a ^ sor elejei illeszkedésre utal, vagyis a ^[0-9-] azt jelenti hogy bármilyen számjeggyel vagy mínusz jellel kezdődik, kérdőjel pedig hogy ez opcionális, tehát egyszer sem vagy pontosan egyszer szerepel. Ez után tetszőleges számjegy következik, és abból legalább egy vagy bármennyi állhat: [0-9]+
Tehát a echo $1 | grep -E '^[0-9-]?[0-9]+$' eredménye az első paramétertől függően vagy nulla hosszúságú karakterlánc lesz (semmi sem jelenik meg), vagy maga szám.
Próbáljuk ez ki terminálban a $1 helyett különböző karaktereket írva:

palferi@lizi:~/proba$ echo 42 | grep -E '^[0-9-]?[0-9]+$'
42
palferi@lizi:~/proba$ echo -23242 | grep -E '^[0-9-]?[0-9]+$'
-23242
palferi@lizi:~/proba$ echo --23242 | grep -E '^[0-9-]?[0-9]+$'
palferi@lizi:~/proba$ echo 2a42 | grep -E '^[0-9-]?[0-9]+$'
palferi@lizi:~/proba$ echo 2-42 | grep -E '^[0-9-]?[0-9]+$'
palferi@lizi:~/proba$

A [ $1 -gt -360 ] && [ $1 -lt 360 ] kifejezés csak akkor lesz igaz, ha két feltételnek is megfelel a paraméter. A radiánra való átszámításnál pi/180-al szorozzuk a fokértéket. Ellenőrizzük a szkript működését különböző paraméterekkel:

palferi@lizi:~/proba$ ./fsin.sc 87
sin(87)=.998629534754573873784487
palferi@lizi:~/proba$ ./fsin.sc --130
A paraméter nem egész szám
palferi@lizi:~/proba$ ./fsin.sc 391
A paraméter étréke nem -360 és 360 között van.

< Vissza

st-linux_alapok/fejezetek/bc-gyak.txt · Utolsó módosítás: 2022/08/25 14:09 szerkesztette: pferi