Provided by:
manpages-pl_20060617-1_all 
NAZWA
bc - język kalkulatora dowolnej precyzji
SKŁADNIA
bc [-hlwsqv] [długie_opcje] [plik...]
WERSJA
Niniejszy podręcznik opisuje GNU bc w wersji 1.06.
OPIS
bc jest językiem obsługującym obliczenia na liczbach dowolnej
dokładności z interaktywnym wykonywaniem instrukcji. Istnieją pewne
podobieństwa składni do języka programowania C. Przy pomocy opcji
wiersza poleceń dostępna jest standardowa biblioteka matematyczna. Na
żądanie, biblioteka matematyczna jest definiowana przed rozpoczęciem
przetwarzania plików. bc rozpoczyna pracę przetwarzając kod z
wszystkich plików wymienionych w wierszu poleceń, zachowując ich
kolejność. Po przetworzeniu wszystkich plików, bc czyta ze
standardowego wejścia. Całość kodu wykonywana jest w miarę czytania.
(Jeśli plik zawiera polecenie zatrzymania procesora, to bc nie będzie
prowadził odczytu ze standardowego wejścia.)
Omawiana wersja bc zawiera kilka rozszerzeń w stosunku do tradycyjnych
realizacji bc i standardu POSIX. Opcje wiersza poleceń mogą powodować,
że rozszerzenia te będą wyświetlać ostrzeżenia lub będą odrzucane.
Niniejszy dokument opisuje język akceptowany przez ten procesor bc.
Rozszerzenia są w nim wyraźnie wyróżnione.
OPCJE
-h, --help
Wypisuje informację o sposobie wywołania i kończy działanie.
-i, --interactive
Wymusza tryb interaktywny.
-l, --mathlib
Definiuje standardową bibliotekę matematyczną.
-w , --warn
Ostrzega o rozszerzeniach w stosunku do POSIX bc.
-s , --standard
Przetwarza wyłącznie standardowy, POSIX-owy język bc.
-q , --quiet
Nie wyświetla zwykłego przywitania GNU bc.
-v , --version
Wypisuje numer wersji, informację o prawach autorskich i kończy
działanie.
LICZBY
Najbardziej podstawowym elementem w bc jest liczba. Liczby są liczbami
dowolnej dokładności. Dokładność ta odnosi się zarówno do części
całkowitej jak i do ułamkowej. Wszystkie liczby są reprezentowane
wewnętrznie w postaci dziesiętnej i wszystkie obliczenia prowadzone są
w układzie dziesiętnym. (Opisywana wersja obcina wyniki operacji
dzielenia i mnożenia.) Liczby posiadają dwa atrybuty: długość i
dokładność. [od tłum.: (org.scale) - w tłumaczeniu używane będzie
słowo `dokładność' w znaczeniu zbliżonym do znanego np. z obsługi
kalkulatorów] Długość jest całkowitą liczbą cyfr znaczących liczby, zaś
dokładność jest całkowitą liczbą cyfr dziesiętnych po kropce
dziesiętnej. Na przykład:
.000001 ma długość 6 i dokładność 6.
1935.000 ma długość 7 i dokładność 3.
ZMIENNE
Liczby przechowywane są w dwu rodzajach zmiennych, zmiennych prostych i
tablicach. Zarówno zmienne proste jak i tablice posiadają nazwy. Nazwy
zaczynają się od litery, po której następuje dowolna liczba liter, cyfr
i znaków podkreślenia. Wszystkie litery muszą być małe. (Nazwy w pełni
alfanumeryczne są rozszerzeniem. W POSIXowym bc wszystkie nazwy są
pojedynczymi małymi literami.) Rodzaj zmiennej wynika z kontekstu, gdyż
po nazwie każdej zmiennej tablicowej wystąpią nawiasy ([]).
Istnieją cztery zmienne specjalne: scale, ibase, obase oraz last. scale
określa, jak niektóre operacje używają cyfr po kropce dziesiętnej.
Domyślną wartością scale jest 0. ibase oraz obase określają podstawę
pozycyjnego systemu liczbowego przy konwersji wejścia i wyjścia.
Domyślną podstawą zarówno dla wejścia jak i dla wyjścia jest 10. last
(rozszerzenie standardu) jest zmienną, która przechowuje wartość
ostatnio wydrukowanej liczby. Zmienne te będą omówione szczegółowo
później, w odpowiedniej części. Wszystkie z nich mogą mieć przypisywane
wartości, jak również mogą być używane w wyrażeniach.
KOMENTARZE
Komentarze w bc rozpoczynają się od znaków /* zaś kończą znakami */.
Komentarze mogą zaczynać się w dowolnym miejscu i na wejściu pojawiają
się jako pojedyncze spacje. (Powoduje to, że komentarze są
ogranicznikami innych elementów wejścia. Na przykład, komentarz nie
może znajdować się w środku nazwy zmiennej.) Komentarze obejmują znaki
nowej linii (końca linii) pomiędzy początkiem a końcem komentarza.
Do zapewnienia obsługi skryptów dla bc, jako rozszerzenie dodano
komentarz w pojedynczym wierszu. Komentarz jednowierszowy rozpoczyna
się znakiem # i rozciąga się do końca wiersza. Znak końca linii nie
jest tu częścią komentarza i jest przetwarzany jak zwykle.
WYRAŻENIA
Liczbami posługują się wyrażenia i instrukcje. Ponieważ język został
zaprojektowany jako interaktywny, instrukcje i wyrażenia wykonywane są
niezwłocznie. Nie ma żadnego programu "głównego" ("main"). Zamiast
tego, kod jest wykonywany zaraz po jego napotkaniu. (Funkcje, omówione
szczegółowo dalej, są zdefiniowane po ich napotkaniu.)
Proste wyrażenie jest po prostu stałą. bc zamienia stałe na wewnętrzne
liczby dziesiętne przy użyciu bieżącej podstawy systemu dla
wprowadzania, podanej w zmiennej ibase. (Istnieje wyjątek dla funkcji.)
Dopuszczalnymi wartościami ibase są 2 do 16. Przypisanie ibase wartości
spoza tego zakresu nada jej wartość 2 lub 16. Liczby wejściowe mogą
zawierać znaki 0-9 oraz A-F. (Uwaga: muszą to być wielkie litery. Małe
litery są nazwami zmiennych.) Liczby jednocyfrowe mają zawsze wartość
cyfry, bez względu na wartość ibase. (tj. A = 10.) Dla liczb
wielocyfrowych bc zamienia wszystkie cyfry wejściowe większe bądź równe
ibase na wartość ibase-1. Powoduje to, że liczba FFF będzie zawsze
największą trzycyfrową liczbą przy danej podstawie systemu dla wejścia.
Pełne wyrażenia są podobne do występujących w wielu językach wysokiego
poziomu. Ponieważ występuje tylko jeden rodzaj liczb, nie ma reguł
określających użycie różnych typów. Zamiast tego istnieją reguły
dotyczące dokładności wyrażeń. Każde wyrażenie posiada określoną
dokładność. Zależy ona od dokładności pierwotnych liczb, wykonywanego
działania i, w wielu przypadkach, wartości zmiennej scale.
Dopuszczalnymi wartościami zmiennej scale są liczby od 0 aż do
maksymalnej liczby, jaka może być reprezentowana jako całkowita
(integer) w języku C.
W podanych poniżej opisach dopuszczalnych wyrażeń, "wyrażenie" określa
pełne wyrażenie a "zmienna" określa zmienną prostą lub tablicową.
Zmienną prostą jest po prostu
nazwa
a zmienna tablicowa jest określona jako
nazwa[wyraenie]
Dokładność wyniku jest maksymalną z dokładności użytych w nim wyrażeń,
chyba że podano inaczej.
- wyrażenie
Wynikiem jest wartość przeciwna do wyrażenia.
++ zmienna
Zmienna jest powiększana o jeden a wynikiem wyrażenia jest ta
nowa wartość.
-- zmienna
Zmienna jest pomniejszana o jeden a wynikiem wyrażenia jest ta
nowa wartość.
zmienna ++
Wynikiem wyrażenia jest wartość zmiennej, a następnie zmienna
jest powiększana o jeden.
zmienna --
Wynikiem wyrażenia jest wartość zmiennej, a następnie zmienna
jest pomniejszana o jeden.
wyrażenie + wyrażenie
Wynikiem tego wyrażenia jest suma obu wyrażeń.
wyrażenie - wyrażenie
Wynikiem tego wyrażenia jest różnica obu wyrażeń.
wyrażenie * wyrażenie
Wynikiem tego wyrażenia jest iloczyn obu wyrażeń.
wyrażenie / wyrażenie
Wynikiem tego wyrażenia jest iloraz obu wyrażeń. Liczba cyfr po
kropce dziesiętnej wyniku jest równa wartości zmiennej scale.
wyrażenie % wyrażenie
Wynikiem tego wyrażenia jest "reszta" z dzielenia obliczana w
następujący sposób. W celu obliczenia a%b, obliczane jest
najpierw a/b z dokładnością do scale cyfr dziesiętnych. Wynik
używany jest do obliczenia a-(a/b)*b z dokładnością określoną
jako maksymalna z scale+scale(b) oraz scale(a). Jeżeli scale
ustawiona jest na zero, zaś oba wyrażenia są całkowite to
wyrażenie to jest funkcją reszty całkowitej.
wyrażenie ^ wyrażenie
Wynikiem tego wyrażenia jest wartość pierwszego z wyrażeń
podniesiona do potęgi określonej przez drugie. Drugie wyrażenie
musi być liczbą całkowitą. (Jeśli drugie wyrażenie nie jest
całkowite, to emitowane jest ostrzeżenie a wyrażenie jest
obcinane tak, by otrzymać wartość całkowitą). Liczba cyfr
ułamkowych wyniku wynosi scale, jeśli wykładnik jest ujemny.
Jeżeli jest on dodatni, to dokładność (liczba cyfr po kropce
dziesiętnej) wyniku stanowi minimum z dokładności pierwszego
wyrażenia przemnożonej przez wartość wykładnika i maksimum z
scale i dokładności pierwszego wyrażenia. To znaczy:
scale(a^b) = min(scale(a)*b, max( scale, scale(a)))
Należy pamiętać, że wyrażenie^0 zawsze zwraca wartość 1.
( wyrażenie )
Nawiasy wymuszają zmianę standardowych priorytetów przy
obliczaniu wyrażenia.
zmienna = wyrażenie
Zmiennej przypisywana jest wartość wyrażenia.
zmienna <op>= wyrażenie
jest to równoważne zapisowi "zmienna = zmienna <op> wyrażenie",
z wyjątkiem tego, iż część "zmienna" jest wyliczana tylko raz.
Może to być istotne, jeśli "zmienna" jest tablicą.
Wyrażenia relacyjne są specjalnym rodzajem wyrażeń, zwracającym zawsze
wartość 0 lub 1: zero jeśli relacja jest fałszywa, zaś 1 jeżeli jest
prawdziwa. Mogą one występować w dowolnych dozwolonych wyrażeniach.
(POSIX bc wymaga, by wyrażenia relacyjne były używane wyłącznie w
instrukcjach if, while i for oraz aby było w nich użyte tylko jedno
sprawdzenie relacji.) Operatorami relacji są:
wyrażenie1 < wyrażenie2
Wynikiem jest jeden jeśli wyrażenie1 jest mniejsze niż
wyrażenie2.
wyrażenie1 <= wyrażenie2
Wynikiem jest 1 gdy wyrażenie jest mniejsze bądź równe
wyrażenie2.
wyrażenie1 > wyrażenie2
Wynikiem jest 1 jeśli wyrażenie1 jest większe niż wyrażenie2.
wyrażenie1 >= wyrażenie2
Wynikiem jest 1 gdy wyrażenie1 jest większe bądź równe
wyrażenie2.
wyrażenie1 == wyrażenie2
Wynikiem jest 1 gdy wyrażenie1 jest równe wyrażenie2.
wyrażenie != wyrażenie2
Wynikiem jest 1 gdy wyrażenie1 nie jest równe wyrażenie2.
Dozwolone są także operacje logiczne. (POSIX bc NIE posiada operacji
logicznych). Wynikami wszystkich operacji logicznych są 0 lub 1 (dla
fałszu i prawdy), tak jak dla wyrażeń relacyjnych. Operatorami
logicznymi są:
!wyrażenie
Zaprzeczenie. Wynikiem jest 1 jeśli wyrażenie ma wartość 0.
wyrażenie && wyrażenie
Koniunkcja. Wynikiem jest 1 jeżeli oba wyrażenia są niezerowe.
wyrażenie || wyrażenie
Alternatywa. Wynikiem jest 1 jeśli dowolne z wyrażeń jest
niezerowe.
Wyrażenia posiadają następujący priorytet: (od najniższego do
najwyższego)
operator ||, wiązanie lewe
operator &&, wiązanie lewe
operator !, niezwiązany
operatory relacji, wiązanie lewe
operator przypisania, wiązanie prawe
operatory + i -, wiązanie lewe
operatory *, / i %, wiązanie lewe
operator ^, wiązanie prawe
jednoargumentowy operator -, niezwiązany
operatory ++ i --, niezwiązane
Kolejność wykonywania została dobrana tak, by programy zgodne z POSIX
bc działały poprawnie. Powoduje to, że operatory relacyjne i logiczne,
użyte w wyrażeniach przypisania, będą wykazywać niecodzienne
zachowywanie. Rozważ wyrażenie:
a = 3 < 5
Większość programistów C uważałaby, że przypisze ono wynik operacji "3
< 5" (wartość 1) zmiennej "a". Tymczasem w bc nadaje ono wartość 3
zmiennej "a", a następnie porównuje 3 z 5. Używając operatorów relacji
i operatorów logicznych z operatorami przypisania najlepiej jest
posłużyć się nawiasami.
bc obsługuje jeszcze kilka innych wyrażeń specjalnych. Związane są one
z funkcjami definiowanymi przez użytkownika i funkcjami standardowymi.
Wszystkie one mają postać "nazwa(parametry)". Funkcje definiowane przez
użytkownika opisano w sekcji Funkcje. Funkcjami standardowymi są:
length ( wyrażenie )
Wynikiem funkcji length jest liczba cyfr znaczących w wyrażeniu.
read ( )
Funkcja ta, będąca rozszerzeniem, odczytuje liczbę ze
standardowego wejścia, niezależnie od miejsca użycia funkcji.
Strzeż się -- może to spowodować kłopoty przy przeplataniu się
danych i programu ze standardowego wejścia. Najlepszym
zastosowaniem tej funkcji jest użycie jej w uprzednio napisanym
programie, który wymaga wprowadzania danych przez użytkownika,
ale nigdy nie pozwala na wprowadzanie kodu programu. Wynikiem
działania funkcji read jest liczba odczytana ze standardowego
wejścia z konwersją układu liczbowego według aktualnej wartości
zmiennej ibase.
scale ( wyrażenie )
Wynikiem funkcji scale jest liczba cyfr po kropce dziesiętnej w
wyrażeniu będącym jej parametrem.
sqrt ( wyrażenie )
Wynikiem funkcji sqrt jest pierwiastek kwadratowy z wyrażenia.
Jeżeli wyrażenie ma wartość ujemną, to generowany jest błąd
wykonania.
INSTRUKCJE
Instrukcje (jak w większości języków algorytmicznych) umożliwiają
sterowanie kolejnością wykonywania wyrażeń. W bc instrukcje wykonywane
są bezzwłocznie, "tak szybko jak to jest możliwe". Wykonanie odbywa się
gdy napotkano znak nowej linii i istnieje jedna lub więcej pełna
instrukcja. W związku z takim natychmiastowym wykonaniem, znaki nowej
linii są bardzo istotne w bc. W rzeczywistości, jako organiczniki
instrukcji używane są zarówno znaki nowej linii jak i średniki.
Nieprawidłowo umieszczony znak nowej linii spowoduje błąd składni.
Ponieważ znaki nowej linii rozdzielają instrukcje, możliwe jest ich
ukrycie (przed interpretacją) przy pomocy znaku odwrotnego ukośnika.
Sekwencja "\<nl>", gdzie <nl> jest znakiem nowej linii postrzegana jest
przez bc jako znak zwykłej spacji zamiast znaku nowej linii. Poniżej
umieszczono listę instrukcji bc i ich znaczenia: (elementy umieszczone
w nawiasach kwadratowych ([]) są opcjonalnymi częściami instrukcji.)
wyrażenie
Instrukcja ta wykonuje dwie rzeczy. jeżeli wyrażenie rozpoczyna
się od "<zmienna> <przypisanie> ...", to jest traktowane jak
instrukcja przypisania. Jeśli wyrażenie nie jest instrukcją
przypisania, to wyrażenie jest wyliczane i drukowane na
standardowym wyjściu. Po wydrukowaniu liczby drukowany jest znak
nowej linii. Na przykład, "a=1" jest instrukcją przypisania zaś
"(a=1)" jest wyrażeniem zawierającym przypisanie. Wszystkie
liczby drukowane są przy użyciu systemu pozycyjnego określonego
zmienną obase. Dopuszczalnymi wartościami obase są 2 do
BC_BASE_MAX. (Patrz sekcja OGRANICZENIA.) Dla podstaw systemu
od 2 do 16 używana jest zwyczajowa metoda zapisu liczb. Dla
podstaw większych od 16 bc posługuje się metodą cyfr
wieloznakowych wyświetlania liczb, gdzie każda z kolejnych cyfr
wyświetlana jest jako liczba dziesiętna. Cyfry wieloznakowe
oddzielane są odstępami. Każda z cyfr zawiera tyle znaków, ile
jest niezbędnych do przedstawienia dziesiętnie wartości
"obase-1". Ponieważ liczby mają dowolną dokładność, niektóre z
liczb mogą nie dać wydrukować się w pojedynczym wierszu. Takie
długie liczby zostaną podzielone między wiersze przy
zastosowaniu "\" jako ostatniego znaku wiersza. Maksymalną
liczbą znaków drukowanych w wierszu jest 70. Z powodu
interaktywneggo charakteru bc drukowanie liczby ma efekt uboczny
w postaci przypisania wydrukowanej wartości do specjalnej
zmiennej o nazwie last. Umożliwia to użytkownikowi odtworzenie
ostatnio wydrukowanej wartości bez potrzeby ponownego wpisywania
wyrażenia, które ją wydrukowało. Nadawanie wartości zmiennej
last jest dozwolone; spowoduje ono zastąpienie ostatnio
wydrukowanej wartości wartością przypisaną. Nowo przypisana
wartość pozostanie aż do wydrukowania kolejnej liczby lub
nadania last innej wartości. (Niektóre z implementacji mogą
dopuszczać użycie pojedynczej kropki (.), nie będącej częścią
liczby, jako skróconej notacji dla last.)
łańcuch
Na wyjściu drukowany jest łańcuch znakowy. Łańcuchy rozpoczynają
się znakiem cudzysłowu i zawierają wszystkie znaki do następnego
znaku cudzysłowu. Wszystkie znaki, włącznie ze znakami nowej
linii, traktowane są dosłownie. Po wydrukowaniu łańcucha nie
jest drukowany znak nowej linii.
print lista
Instrukcja print (rozszerzenie) umożliwia użycie innego sposobu
wydruku wyników. "Lista" jest listą łańcuchów i wyrażeń
oddzielonych przecinkami. Każdy łańcuch czy wyrażenie drukowany
jest w kolejności występowania na liście. Nie jest drukowany
kończący znak nowej linii (przejście do następnego wiersza).
Wyliczana jest wartość wyrażeń; jest ona drukowana i
przypisywana zmiennej last. Łańcuchy użyte w instrukcji print są
drukowane na wyjściu i mogą zawierać znaki specjalne. Znaki
specjalne rozpoczynają się znakiem odwrotnego ukośnika (\). bc
rozpoznaje następujące znaki specjalne: "a" (dzwonek, bell), "b"
(backspace), "f" (wysuw strony, form feed), "n" (nowa linia,
newline), "r" (powrót karetki, carriage return), "q" (cudzysłów,
double quote), "t" (tabulacja, tab) oraz "\" (odwrotny ukośnik,
backslash). Inne znaki występujące po odwrotnym ukośniku będą
ignorowane.
{ lista_instrukcji }
Jest to instrukcja grupowania. Pozwala na grupowanie wielu
instrukcji do wykonania.
if ( wyrażenie ) instrukcja1 [else instrukcja2]
Instrukcja if oblicza wyrażenie i wykonuje instrukcję1 bądź
instrukcję2 w zależności od wartości wyrażenia. Jeżeli wyrażenie
jest niezerowe, wykonywana jest instrukcja1. Jeśli występuje
instrukcja2 a wartością wyrażenia jest 0, to wykonywana jest
instrukcja2. (Klauzula else instrukcji if jest rozszerzeniem).
while ( wyrażenie ) instrukcja
Instrukcja while powtarza wykonywanie danej instrukcji póki
wyrażenie jest niezerowe. Oblicza ona wartość wyrażenia przed
każdym wykonaniem instrukcji. Przerwanie pętli powodowane jest
zerową wartością wyrażenia lub wykonaniem instrukcji break
(przerwania).
for ( [wyr1] ; [wyr2] ; [wyr3] ) instrukcja
Instrukcja for kontroluje powtarzane wykonanie danej instrukcji.
Przed pętlą obliczane jest wyrażenie1. Wyrażenie2 jest obliczane
przed każdym wykonaniem instrukcji. Jeśli jest niezerowe, to
wykonywana jest instrukcja. Jeśli ma ono wartość zero, to pętla
jest przerywana. Po każdym wykonaniu danej instrukcji wyliczana
jest wartość wyrażenia3 przed ponownym wyliczeniem wyrażenia2.
Jeżeli pominięto wyrażenie1 lub wyrażenie3, to nic nie jest
obliczane w chwili, gdy powinna być określana ich wartość.
Jeżeli pominięto wyrażenie2, to jest ono zastępowane wartością
1. (Wyrażenie opcjonalne stanowią rozszerzenie. bc w POSIXie
wymaga wszystkich trzech wyrażeń.) Poniższy kod jest równoważny
instrukcji for:
wyrażenie1;
while (wyrażenie2) {
instrukcja;
wyrażenie3;
}
break Instrukcja ta powoduje wymuszone zakończenie ostatniej
obejmującej ją instrukcji while lub for.
continue
Instrukcja continue (rozszerzenie) powoduje rozpoczęcie kolejnej
iteracji przez ostatnią obejmującą ją instukcję for.
halt Instrukcja halt (rozszerzenie) jest instrukcją nakazującą
preprocesorowi bc zakończenie pracy (ale tylko wtedy gdy
instrukcja ta jest wykonywana). Na przykład, "if (0 == 1) halt"
nie spowoduje przerwania pracy bc, gdyż instrukcja halt nie
będzie wykonana.
return Zwraca wartość zero jako wynik funkcji. (Patrz sekcja dotycząca
funkcji).
return ( wyrażenie )
Zwraca wartość wyrażenia jako wynik funkcji. (Patrz sekcja
dotycząca funkcji). Nawiasy nie są wymagane, co jest
rozszerzeniem GNU bc.
PSEUDO-INSTRUKCJE
Te instrukcje nie są instrukcjami w tradycyjnym sensie tego terminu.
Nie są one instrukcjami wykonywanymi. Ich funkcja jest wykonywana
podczas "kompilacji".
limits Wypisuje lokalne ograniczenia narzucone przez lokalna wersję bc.
Jest to rozszerzenie.
quit Po odczycie instrukcji quit procesor bc kończy pracę,
niezależnie od tego, gdzie wystąpiła ta instrukcja. Na przykład,
"if (0 == 1) quit" spowoduje zakończenie pracy bc.
warranty
Wypisuje dłuższą notkę na temat gwarancji. Jest to rozszerzenie.
FUNKCJE
Funkcje dostarczają sposobu definiowania obliczeń, które mogą być
wykonane później. Funkcje w bc zawsze obliczają wartość i zwracają ją
do miejsca wywołania. Definicje funkcji są "dynamiczne" w tym sensie,
że funkcja pozostaje niezdefiniowana dopóki na wejściu nie zostanie
odczytana jej definicja. Definicja ta jest następnie używana dopóki nie
zostanie napotkana inna definicja funkcji o tej samej nazwie. Wówczas
nowa definicja zastępuje starszą. Funkcja definiowana jest następująco:
define nazwa ( parametry ) { nowa_linia
lista_auto lista_instrukcji }
Wywołanie funkcji jest po prostu wyrażeniem postaci "nazwa(parametry)".
Parametry są liczbami lub tablicami (rozszerzenie). W definicji funkcji
definiuje się równocześnie jest zero lub więcej jej parametrów przez
podanie ich nazw rozdzielonych przecinkami. Liczby są jedynymi
parametrami wywoływanymi przez wartość. Tylko tablice są wołane przez
wskazanie zmiennej. Tablice podawane są w definicji parametrów przy
pomocy notacji "nazwa[ ]". W wywołaniu funkcji parametry rzeczywiste
dla parametrów numerycznych są pełnymi wyrażeniami. Do przekazywania
tablic używana jest ta sama notacja, co przy definiowaniu parametrów
typu tablicowego. Dana tablica przesyłana jest do funkcji przez nazwę
(wskazanie). Ponieważ definicje funkcji są dynamiczne, w trakcie
wywoływania funkcji sprawdzana jest liczba i typy jej parametrów.
Niezgodnośc liczby parametrów lub ich typów powoduje błąd wykonania.
Błąd wykonania pojawi się także przy próbie wywołania niezdefiniowanej
funkcji.
lista_auto jest opcjonalną listą zmiennych, do użytku "lokalnego". A
oto składnia tej listy (jeśli występuje): "auto nazwa, ... ;". Średnik
jest opcjonalny. Każda z nazw jest nazwą auto-zmiennej. Tablice mogą
być podane przy użyciu takiej samej składni jak w parametrach. Na
początku funkcji wartości tych zmiennych odkładane są na stosie.
Następnie zmienne są inicjowane zerami i używane w czasie wykonywania
funkcji. Przy zakończeniu funkcji zmienne są zdejmowane ze stosu, tak
że przywracana jest ich pierwotna wartość (z momentu wywołania
funkcji). Parametry te są faktycznie zmiennymi auto inicjowanymi
wartościami dostarczonymi w wywołaniu funkcji. Zmienne typu auto różnią
się od tradycyjnych zmiennych lokalnych, gdyż jeśli funkcja A woła
funkcję B, to B może posługiwać się zmiennymi auto funkcji A po prostu
używając tych samych nazw, chyba że funkcja B traktuje je jako zmienne
auto. Ponieważ zmienne auto i parametry składowane są na stosie, to bc
obsługuje funkcje rekurencyjne.
Ciało funkcji jest listą instrukcji bc. I znów, jak w części
zasadniczej, instrukcje oddzielane są średnikami lub znakami nowej
linii. Instrukcje return (powrót) powodują zakończenie funkcji i
zwrócenie wartości. Istnieją dwa warianty instrukcji return. Pierwsza
postać, "return", zwraca wartość 0 do wywołującego wyrażenia. Druga
postać, "return ( wyraenie )", oblicza wartość wyrażenia i zwraca ją
do wyrażenia wołającego. Każda funkcja domyślnie kończy się niejawną
instrukcją "return (0)". Pozwala to na funkcji na zakończenie działania
i zwrócenie zera bez jawnej instrukcji powrotu.
Funkcje inaczej korzystają ze zmiennej ibase. Wszystkie stałe w obrębie
ciała funkcji będą konwertowane przy zastosowaniu wartości ibase w
momencie wywołania funkcji. Zmiany ibase w czasie wykonywania funkcji
są ignorowane, z wyjątkiem funkcji standardowej read, która zawsze do
konwersji liczb wykorzystuje bieżącą wartość ibase.
Rozszerzeniem GNU bc jest nieco luźniejszy format dla definicji.
Standard wymaga, by nawias otwierający znajdował się w tym samym
wierszu co słowo kluczowe define, a wszystkie pozostałe części w
kolejnych wierszach. Opisywana tu wersja bc zezwala na dowolną ilość
znaków nowej linii przed i po nawiasie otwierającym funkcji. Na
przykład, dozwolone są poniższe definicje.
define d (n) { return (2*n); }
define d (n)
{ return (2*n); }
BIBLIOTEKA MATEMATYCZNA
Jeżeli bc wywoływane jest z opcją -l, to wstępnie wczytywana jest
biblioteka matematyczna (math library), a domyślna liczba cyfr
dziesiętnych (scale) ustawiana jest na 20. Funkcje matematyczne
obliczają swe wyniki z dokładnością określoną w momencie ich wywołania.
Bibilioteka matematyczna definiuje następujące funkcje:
s(x) Sinus x, x podawany jest w radianach.
c(x) Cosinus x, x w radianach.
a(x) Arcus tangens x; arcus tangens zwraca radiany.
l(x) Logarytm naturalny z x.
e(x) Funkcja wykładnicza - e do potęgi x.
j(n,x) Funkcja Bessela rzędu n (całkowitego) z argumentem x.
PRZYKŁADY
W powłoce /bin/sh, poniższe polecenie przypisuje wartość liczby "Pi"
zmiennej środowiska pi.
pi=$(echo "scale=10; 4*a(1)" | bc -l)
Poniżej podano definicję funkcji wykładniczej używanej w bibliotece
matematycznej. Funkcja ta napisana jest w bc standardu POSIX.
scale = 20
/* wykorzystuje fakt, że e^x = (e^(x/2))^2
Gdy x jest dostatecznie małe, używamy szeregu:
e^x = 1 + x + x^2/2! + x^3/3! + ...
*/
define e(x) {
auto a, d, e, f, i, m, v, z
/* sprawdzenie znaku x */
if (x<0) {
m = 1
x = -x
}
/* przewidywane x */
z = scale;
scale = 4 + z + .44*x;
while (x > 1) {
f += 1;
x /= 2;
}
/* inicjowanie zmiennych */
v = 1+x
a = x
d = 1
for (i=2; 1; i++) {
e = (a *= x) / (d *= i)
if (e == 0) {
if (f>0) while (f--) v = v*v;
scale = z
if (m) return (1/v);
return (v/1);
}
v += e
}
}
Poniższy kod posługuje się rozszerzonymi cechami bc do uzyskania
prostego programu liczącego salda książeczki czekowej. Najlepiej byłoby
zachować go w pliku, tak by mógł być wykorzystany wielokrotnie bez
potrzeby każdorazowego przepisywania.
scale=2
print "\nProgram książeczki czekowej!\n"
print " Pamiętaj, wpłaty są transakcjami ujemnymi.\n"
print " Koniec - transakcja zerowa.\n\n"
print "Saldo początkowe? "; bal = read()
bal /= 1
print "\n"
while (1) {
"bieżące saldo = "; bal
"transakcja? "; trans = read()
if (trans == 0) break;
bal -= trans
bal /= 1
}
quit
Poniżej zamieszczono definicję rekurencyjnej funkcji silni.
define f (x) {
if (x <= 1) return (1);
return (f(x-1) * x);
}
OPCJE READLINE I LIBEDIT
GNU bc może zostać skompilowany (poprzez opcję konfiguracji) tak, by
posługiwał się biblioteką GNU edytora wejścia o nazwie readline lub też
biblioteką BSD libedit. Umożliwia to użytkownikowi edycję wierszy
przed wysłaniem ich do bc. Pozwala też na wykorzystanie historii
poprzednio wprowadzonych wierszy. Przy wybraniu tej opcji bc posiada
dodatkową zmienną specjalną. Ta specjalna zmienna, history, przechowuje
liczbę zachowywanych wierszy historii. Dla readline, wartość -1
oznacza, że przechowywana jest nieograniczona liczba wierszy historii.
Ustawienie wartości history na liczbę dodatnią ogranicza liczbę
przechowywanych wierszy historii do podanej liczby. Wartość zero
wyłącza funkcję historii wprowadzonych wierszy. Wartością domyślną jest
100. Więcej informacji można znaleźć w podręcznikach użytkownika dla
bibliotek GNU readline i history oraz BSD libedit. Nie można
równocześnie włączyć zarówno readline jak i libedit.
RÓŻNICE
Niniejsza wersja bc została zbudowana w oparciu o projekt POSIX
P1003.2/D11 i zawiera kilka różnic i rozszerzeń w stosunku do tego
dokumentu i tradycyjnych realizacji. Nie jest wykonana w tradycyjny
sposób, wykorzystujący polecenie dc(1). Wersja ta jest pojedynczym
procesem, analizującym i uruchamiającym kod binarny będący tłumaczeniem
programu. Istnieje "nieudokumentowana" opcja (-c) powodująca, że
program wyświetla kod binarny na standardowym wyjściu zamiast
wykonywania go. Używana była ona głównie do debuggowania analizatora
składni i przy przygotowaniu biblioteki matematycznej.
Głównym źródłem różnic są rozszerzenia, w których jakaś cecha,
możliwość programu jest rozbudowana w celu dodania funkcjonalności,
oraz dodatki, gdzie dodano nowe możliwości. Poniżej podano listę
różnic i rozszerzeń.
Zmienna środowiska LANG
Niniejsza wersja nie spełnia standardu POSIX przetwarzania
zmiennej środowiska LANG i wszystkich zmiennych środowiska
rozpoczynających się na LC_.
nazwy Tradycyjny i POSIXowy bc posiadają jednoliterowe nazwy funkcji,
zmiennych i tablic. Zostały one rozszerzone do nazw
wieloznakowych, rozpoczynających się literą i mogących zawierać
litery, cyfry i znaki podkreślenia.
łańcuchy
Łańcuchy nie mogą zawierać znaków NUL. POSIX stwierdza, że
wszystkie znaki muszą być zawarte w łańcuchach.
last POSIX bc nie posiada zmiennej last. Niektóre implementacje bc
używają kropki (.) w podobny sposób.
porównania
POSIX bc dopuszcza porównania wyłącznie w instrukcjach if, while
oraz w drugim wyrażeniu instrukcji for. Dodatkowo, w każdej z
tych instrukcji dopuszczalna jest tylko jedna operacja
porównania (relacji).
instrukcja if, klauzula else
POSIX bc nie posiada klauzuli else.
instrukcja for
POSIX bc wymaga by w instrukcji for występowały wszystkie
wyrażenia.
&&, ||, !
POSIX bc nie posiada operatorów logicznych.
funkcja read
POSIX bc nie posiada funkcji read.
instrukcja print
POSIX bc nie posiada instrukcji print.
instrukcja continue
POSIX bc nie posiada instrukcji continue.
instrukcja return
POSIX bc wymaga nawiasów wokół zwracanego wyrażenia.
parametry tablicowe
POSIX bc nie obsługuje (obecnie) w pełni parametrów tablicowych.
Gramatyka POSIX zezwala na użycie tablic w definicjach funkcji,
ale nie zapewnia metody przekazania tablicy jako bieżącego
parametru. (Jest to najprawdopodobniej przeoczenie w
zdefiniowanej gramatyce.) Tradycyjne implementacje bc posiadają
jedynie wywołanie parametrów tablicowych przez wartość.
format funkcji
POSIX bc wymaga, by nawias otwierający był w tym samym wierszu,
co słowo kluczowe define, zaś instrukcja auto w następnym
wierszu.
=+, =-, =*, =/, =%, =^
POSIX bc nie wymaga, by były zdefiniowane powyższe operatory
przypisania "starego typu". Niniejsza wersja zezwala na takie
przypisania w "starym stylu". Należy skorzystać z instrukcji
limits, by stwierdzić, czy zainstalowana wersja je rozpoznaje.
Jeżeli obsługuje ona przypisania w "starym stylu", to instrukcja
"a =- 1" pomniejszy a o jeden zamiast przypisać a wartość -1.
spacje w liczbach
Inne implementacje bc dopuszczają występowanie spacji w
liczbach. Na przykład, "x=1 3" przypisze wartość 13 zmiennej x.
Ta sama instrukcja spowoduje błąd składni w opisywanej tu wersji
bc.
błędy i wykonanie
Opisywana implementacja różni się od innych sposobem, w jaki
wykonywany jest kod w przypadku znalezienia w programie błędów
składniowych i innych. W przypadku napotkania błędu w definicji
funkcji, obsługa błędów próbuje odnależć początek instrukcji i
kontynuować analizę składniową funkcji. Po znalezieniu błędu w
funkcji, nie jest ona możliwa do wywołania i staje się
niezdefiniowana. Błędy składniowe w interaktywnym wykonywaniu
kodu unieważniają bieżący blok wykonania. Blok wykonania jest
zakończony końcem linii pojawiającym się po pełnej sekwencji
instrukcji. Na przykład,
a = 1
b = 2
posiada dwa bloki wykonania a
{ a = 1
b = 2 }
ma jeden blok wykonania. Każdy z błędów wykonania przerywa
wykonywanie bieżącego bloku wykonania. Ostrzeżenie w trakcie
wykonywania nie przerywa bieżącego bloku.
Przerwania
Podczas sesji interaktywnej sygnał SIGINT (zwykle generowany
przez znak control-C z terminala) spowoduje przerwanie bieżącego
bloku wykonywania. Wyświetli on błąd wykonania ("runtime"),
wskazujący która funkcja została przerwana. Po wyczyszczeniu
wszystkich struktur (runtime structures) wykonania, zostanie
wyświetlony komunikat informujący użytkownika, że bc jest gotów
do przyjmowania kolejnych danych. Wszystkie uprzednio
zdefiniowane funkcje pozostają zdefiniowane, zaś wartości
wszystkich zmiennych innych niż zmienne typu auto są wartościami
sprzed przerwania. Podczas procesu oczyszczania struktur danych
usuwane są wszystkie zmienne typu auto oraz parametry funkcji.
W czasie sesji nieinteraktywnej sygnał SIGINT przerywa wykonanie
całego bc.
OGRANICZENIA
Poniżej podano obecne ograniczenia opisywanego procesora bc. Niektóre
z nich mogą być zmienione podczas instalacji. Faktyczne ograniczenia
można sprawdzić za pomocą instrukcji limits (ograniczenia).
BC_BASE_MAX
Maksymalna podstawa pozycyjnego układu, w którym wyprowadzane są
wyniki obecnie ustawiona jest na 999. Maksymalną podstawą układu
wejściowego jest 16.
BC_DIM_MAX
Obecnie ustawione jest arbitralne ograniczenie do 65535 (w
wersji rozpowszechnianej). Twoja instalacja może być inna.
BC_SCALE_MAX
Liczba cyfr po kropce dziesiętnej ograniczona jest do INT_MAX
cyfr. Także liczba cyfr przed kropką dziesiętną ograniczona jest
do INT_MAX cyfr.
BC_STRING_MAX
Maksymalnie w łańcuchu może wystąpić INT_MAX znaków.
wykładnik
Wartość wykładnika w operacji potęgowania (^) ograniczona jest
do LONG_MAX.
nazwy zmiennych
Obecnie nie może być więcej niż 32767 unikalnych nazw w każdym z
rodzajów: zmiennych prostych, tablic i funkcji.
ZMIENNE ŚRODOWISKA
bc przetwarza następujące zmienne środowiska:
POSIXLY_CORRECT
To samo, co opcja -s. Tryb zgodności z POSIX.
BC_ENV_ARGS
Inny sposób przekazywania argumentów do bc. Format jest taki
sam, jak argumentów wiersza poleceń. Argumenty te przetwarzane
są na początku, więc pliki podane w argumentach środowiska
przetwarzane są przed plikami podanymi jako argumenty wiersza
poleceń. Umożliwia to użytkownikowi ustawienie "standardowych"
opcji i plików, jakie będą przetwarzane przy każdym wywołaniu
bc. Pliki podane w zmiennych środowiska zawierają zwykle
definicje funkcji, które użytkownik chce mieć zdefiniowane przy
każdym uruchomieniu bc.
BC_LINE_LENGTH
Powinna to być liczba całkowita (integer) podająca ilość znaków
w wierszu wynikowym. Obejmuje ona znaki odwrotnego ukośnika i
nowej linii dla długich liczb.
DIAGNOSTYKA
Jeżeli któryś z plików podanych w wierszu poleceń nie może zostać
otwarty bc zgłosi, że plik ten jest niedostępny i przerwie pracę.
Istnieją też komunikaty diagnostyczne kompilacji i wykonania, które
powinny być zrozumiałe.
BŁĘDY
Obsługa błędów (error recovery) nie jest jeszcze bardzo dobra.
Błędy proszę zgłaszać (w jęz.angielskim) na adres bug-bc@gnu.org.
Upewnij się, że pole tematu wiadomości zawiera gdzieś słowo ``bc''.
AUTOR
Philip A. Nelson
phil@cs.wwu.edu
PODZIĘKOWANIA
Autor chciałby podziękować Steve'owi Sommars (Steve.Sommars@att.com) za
jego szeroką pomoc w testowaniu tej implementacji. Podsunął on wiele
cennych sugestii. Dzięki jego zaangażowaniu jest to o wiele lepszy
produkt.
ZOBACZ TAKŻE
dc(1), expr(1), awk(1)