Wykonywanie prostych obliczeń z poziomu powłoki

Transkrypt

Wykonywanie prostych obliczeń z poziomu powłoki
LINUX USER
Wiersz poleceń
bash i bc
Wykonywanie
prostych obliczeń
z poziomu powłoki
Nie zawsze do prostych obliczeń trzeba używać kalkulatora, takiego jak xcalc czy Kcalc – przecież
bash może obsłużyć proste operacje arytmetyczne,
a do bardziej zaawansowanych zastosowań zawsze
możemy użyć bc.
HEIKE JURZIK
Poproszę o wiersz poleceń
Najczęściej używaną powłoką użytkownika
w Linuksie jest Bourne Again Shell, czyli
Bash. Powłoka odbiera i interpretuje komendy, uruchamia programy i zarządza procesami. Dodatkowo bash przechowuje zmienne
środowiskowe i zezwala na ich użycie innym
programom. Poza różnorakimi możliwościami programowania, bash potrafi obsługiwać
cztery podstawowe operacje matematyczne
(dodawanie, odejmowanie, mnożenie i dzielenie) oraz operacje modulo, potrafi zatem wyznaczać wartości wyrażeń matematycznych.
Jakkolwiek, obsługując tylko liczby całkowite (liczby całkowite bez pozycji po przecinku) do 32 bitów, bash nie jest matematycznym geniuszem. Jeżeli musimy popracować
z liczbami zmiennoprzecinkowymi, spróbujmy użyć bc, „Basic Calculator”. Program może być używany zarówno interaktywnie jak
i w formie skryptowej.
Jak rachować
Do wykonywania operacji matematycznych
bash wymaga specjalnej składni. Starsze wersje muszą dodawać przedrostek dolara i zamykać wyrażenia matematyczne w nawiasach
92
Maj 2004
kwadratowych. Bash 2.0 i późniejsze wymagają zamykania wyrażeń w podwójnych nawiasach zwykłych. Mimo że późniejsze wersje
powłoki bash obsługują starsze notacje, my
pozostaniemy w naszych dalszych przykładach przy podwójnych nawiasach zwykłych.
Bash wykonuje obliczenia na „zwyczajnych” liczbach oraz na zmiennych, na przykład:
hj@asteroid:~$ echo $((1+1))
2
Alternatywnie, możemy zdefiniować zmienne
i przed użyciem w obliczeniach przyporządkować im wartości:
hj@asteroid:~$
hj@asteroid:~$
hj@asteroid:~$
20
hj@asteroid:~$
-1
a=4
b=5
echo $((a*b))
echo $((a-b))
Żeby zmieścić wyrażenia oraz obliczenia
w pojedynczej linii, używamy średnika, który
łączy poszczególne polecenie. Poprzedni
www.linux-magazine.pl
przykład może być również przedstawiony
w pojedynczym wierszu, jak niżej
a=4; b=5; echo $((a*b))
Inne operatory to znak minus (-) dla odejmowania, gwiazdka (*) dla mnożenia i ukośnik
w prawo (/) dla dzielenia liczb całkowitych.
Podwójna gwiazdka (**) jest używana jako
operator wykładniczy, np. echo
$((2**16)), znak
procent jest operatorem modulo, który ustala
resztę z dzielenia liczb całkowitych, np. ec
$((5%3)) równa się 2, jako że 2 jest resztą
z dzielenia 5 przez 3.
Jak sobie radzić z liczbami
zmiennoprzecinkowymi?
Jeżeli napiszemy: echo
$((1/3)), to zauważymy, że
nie jest to tak naprawdę dzielenie liczb całkowitych, ale mimo to bash nie potrafi obsługiwać liczb zmiennoprzecinkowych. Wejdziemy do bc. W celu uruchomienia kalkulatora
wpisujemy bc.
Za pierwszym razem użytkownicy mogą
być zakłopotani faktem, że po wykonaniu polecenia nie widać kursora. Bez paniki – bc
czeka na wprowadzenie danych. Wyjść z kal-
Wiersz poleceń
kulatora możemy wpisując quit lub naciskając [Ctrl-d].
Jak można oczekiwać, wyrażenia arytmetyczne mogą być formułowane za pomocą
zwykłych operatorów: +, -, *, i / oraz nawiasów.
(1.1+2)*2 [Return]
6.2
Po wpisaniu wyrażenia naciskamy [Enter], bc
natychmiast zwróci wynik. Średnik wpisujemy dla oddzielenia od siebie operacji:
1.1+2; 3.1-2 [Return]
3.1
1.1
bc przechowuje historie wszystkich poleceń,
pozwalając za pomocą klawiszy strzałek na
przewijanie do przodu i do tyłu pośród ostatnio użytych poleceń, tak samo jak to jest
w powłoce.
Cztery podstawowe operacje matematyczne w bc są identyczne z używanymi w bash,
lecz operatory wykładnicze się różnią. Zamiast podwójnej gwiazdki, bc używa znaku
daszka (^).
Zmienne
Jeżeli wielokrotnie będziemy używać tej samej liczby do obliczeń, sensownym wydaje
się zdeklarowanie jej jako zmiennej. Znak
równości jest używany do przyporządkowania
wartości do zmiennej, na przykład:
a=201; b=300
Niestety, bc nie pokazuje, czy zapisał zmienną. Aby wyświetlić wartości a i b musimy wpisać nazwę zmiennej i nacisnąć [Enter] – rzeczywiście bc jest wyjątkowo oschły.
Każda zdefiniowana zmienna może być
użyta w obliczeniach jako liczba:
a*b
60300
a+b
501
Możemy się nieco zdziwić próbując podzielić
te dwie zmienne: bc zwróci jako wynik 0. Aby
obsługiwać operacje zmiennoprzecinkowe,
musimy wyspecyfikować opcje -l podczas
uruchamiania programu. Na szczęście jest
także sposób, aby dodać wsparcie zmiennoprzecinkowe podczas pracy z programem.
Wpisujemy scale=value (gdzie value to liczba
całkowita pomiędzy 9 i 99), aby określić liczbę miejsc dziesiętnych wyświetlanych (i obliczanych) przez bc:
scale=23 [Return]
a/b [Return]
.67000000000000000000000
Podczas wykonywania dzielenia możemy zauważyć, że bc cierpi na te same bolączki, co
każdy inny program działający na liczbach
zmiennoprzecinkowych: błędy w zaokrąglaniu. Na przykład, 1/3*3 zwraca wartość
0.999999999 (liczba dziewiątek wskazuje
zdefiniowaną przez nas liczbę miejsc po
przecinku), podczas gdy matematycznie równoważne wyrażenie 1/(3/3) jest obliczane poprawnie zwracając 1.
Trzeba przyznać, że bc obsługuje liczby
ujemne naprawdę dobrze. Wystarczy postawić znak minus przed liczbą:
a + -b
-99
-a
-201
Inne światy
Program bc ma w zanadrzu całkiem sporo
sztuczek, na przykład funkcje matematyczne,
takie jak potęgowanie:
sqrt(144)
12
Domyślnie bc będzie używał systemu dziesiętnego, ale bardzo łatwo zmienić na inną
podstawę:
ibase=16
A
10
Wszystko co zostanie wpisane po poleceniu
iba
se będzie interpretowane przez bc jako dane
w formacie szesnastkowym – włączając w to
polecenie powrotu do systemu dziesiętnego,
iba
se=10. Oczywiście bc oczekuje danych szesnastkowych i poprawnie interpretuje 10 jako
16 w systemie dziesiętnym. Składnia w tym
przypadku to iba
se=A. Aby sprawdzić, jaką
podstawę program aktualnie wykorzystuje,
piszemy iba
se bez żadnych parametrów.
Podczas gdy iba
se ustawia format wejścia,
oba
se określa podstawę dla wyjścia. Gdybyśmy
byli zainteresowani tym, jaka jest wartość
liczby 15 w systemie szesnastkowym, piszemy
jak niżej:
LINUX USER
obase=16 [Return]
15 [Return]
F
Nie powinniśmy mieć żadnych trudności
z przestawieniem z powrotem oba
se na podstawę 10. Sztuczkę tą wykonamy za pomocą obase=10, zakładając że nie zmienialiśmy wcześniej formatu wejściowego iba
se.
Warto sprawdzić
Program bc jest językiem programowania,
pozwala to programowi na używanie struktur
sterujących, podobnych do używanych przez
C lub C++, co umożliwia bardziej złożone
zastosowania. Żeby wyświetlić kwadraty numerów od 1 do 10, użyjemy prostej pętli f
oszczędzając tym samym dużo pisania:
for (i=1; i<=10; i++) U
print i^2,'\n';
1
4
9
16
25
36
49
64
81
100
Składnia użyta w pętli jest łatwa do zrozumienia – instrukcja, a następnie trzy wyrażenia
w nawiasach. Pierwsze wyrażenie (i=1) jest wykonywane tylko raz przed przetwarzaniem pętli. Pętla jest wykonywana dopóki drugie wyrażenie nie będzie prawdziwe, czyli aż i<=10.
Trzecie wyrażenie jest wykonywane przy każdym powtórzeniu, tzn. zwiększa się wartość i.
Nie ma potrzeby uruchamiania bc za każdym razem, kiedy chcemy wykonać proste obliczenie, wpisujemy polecenie i zamykamy program. Możemy użyć potoków do przekazania
obliczeń do bc, co jest w rzeczywistości potajemnym sposobem użycia powłoki bash do wykonywania zmiennoprzecinkowych obliczeń:
hj@asteroid:~$ echo 1/3 | bc -l
.33333333333333333333
Używając apostrofu (`) można nawet przechować obliczenia w zmiennych powłoki:
x=`echo '$a*$b' | bc -l`
pomnoży wartości zmiennych powłoki a i b
i zapisze wynik w x.
■
www.linux-magazine.pl
Maj 2004
93