bc(1) General Commands Manual bc(1)

bc - język kalkulatora dowolnej precyzji

bc [ -hlwsqv ] [długie-opcje] [ plik ... ]

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.

Wypisuje informację o sposobie wywołania i kończy działanie.
Wymusza tryb interaktywny.
Definiuje standardową bibliotekę matematyczną.
Ostrzega o rozszerzeniach w stosunku do POSIX bc.
Przetwarza wyłącznie standardowy, POSIX-owy język bc.
Nie wyświetla zwykłego przywitania GNU bc.
Wypisuje numer wersji, informację o prawach autorskich i kończy działanie.

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 mają 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 dziesiętnych liczby, używanej przez bc do jej reprezentacji, 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.

Liczby przechowywane są w dwu rodzajach zmiennych, zmiennych prostych i tablicach. Zarówno zmienne proste, jak i tablice mają 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 POSIX-owym 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 w bc rozpoczynają się od znaków /*, a 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.

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).

A simple expression is just a constant. bc converts constants into internal decimal numbers using the current input base, specified by the variable ibase. (There is an exception in functions.) The valid values for ibase are 2 through 36. (Bases greater than 16 are an extension.) Assigning a value outside this range to ibase will result in a value of 2 or 36. Input numbers may contain the characters 0-9 and A-Z. (Note: They must be capitals. Lower case letters are variable names.) Single digit numbers always have the value of the digit regardless of the value of ibase. (i.e. A = 10.) For multi-digit numbers, bc changes all input digits greater or equal to ibase to the value of ibase-1. This makes the number ZZZ always be the largest 3 digit number of the input base.

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 ma 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.

In the following descriptions of valid expressions, "expr" refers to a complete expression and "var" refers to a simple or an array variable. A simple variable is just a

nazwa
a zmienna tablicowa jest określona jako
nazwa[wyrażenie]
Dokładność wyniku jest maksymalną z dokładności użytych w nim wyrażeń, chyba że podano inaczej.
Wynikiem jest wartość przeciwna do wyrażenia.
++ zmienna
Zmienna jest powiększana o jeden a wynikiem wyrażenia jest ta nowa wartość.
Zmienna jest pomniejszana o jeden a wynikiem wyrażenia jest ta nowa wartość.
The result of the expression is the value of the variable and then the variable is incremented by one.
Wynikiem wyrażenia jest wartość zmiennej, a następnie zmienna jest pomniejszana o jeden.
Wynikiem tego wyrażenia jest suma obu wyrażeń.
Wynikiem tego wyrażenia jest różnica obu wyrażeń.
Wynikiem tego wyrażenia jest iloczyn obu wyrażeń.
Wynikiem tego wyrażenia jest iloraz obu wyrażeń. Liczba cyfr po kropce dziesiętnej wyniku jest równa wartości zmiennej scale.
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.
The result of the expression is the value of the first raised to the second. The second expression must be an integer. (If the second expression is not an integer, a warning is generated and the expression is truncated to get an integer value.) The scale of the result is scale if the exponent is negative. If the exponent is positive the scale of the result is the minimum of the scale of the first expression times the value of the exponent and the maximum of scale and the scale of the first expression. (e.g. scale(a^b) = min(scale(a)*b, max( scale, scale(a))).) It should be noted that expr^0 will always return the value of 1.
( wyrażenie )
Nawiasy wymuszają zmianę standardowych priorytetów przy obliczaniu wyrażenia.
Zmiennej przypisywana jest wartość wyrażenia.
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ą.

Relational expressions are a special kind of expression that always evaluate to 0 or 1, 0 if the relation is false and 1 if the relation is true. These may appear in any valid expression. (POSIX bc requires that relational expressions are used only in if, while, and for statements and that only one relational test may be done in them.) The relational operators are

Wynikiem jest 1, jeśli wyrażenie1 jest mniejsze niż wyrażenie2.
Wynikiem jest 1, gdy wyrażenie jest mniejsze bądź równe wyrażenie2.
Wynikiem jest 1, jeśli wyrażenie1 jest większe niż wyrażenie2.
Wynikiem jest 1, gdy wyrażenie1 jest większe bądź równe wyrażenie2.
Wynikiem jest 1, gdy wyrażenie1 jest równe wyrażenie2.
Wynikiem jest 1, gdy wyrażenie1 nie jest równe wyrażenie2.

Boolean operations are also valid. (POSIX bc does NOT have boolean operations). The result of all boolean operations are 0 and 1 (for false and true) as in relational expressions. The boolean operators are:

!wyrażenie
Zaprzeczenie. Wynikiem jest 1, jeśli wyrażenie ma wartość 0.
Koniunkcja. Wynikiem jest 1, jeżeli oba wyrażenia są niezerowe.
Alternatywa. Wynikiem jest 1, jeśli dowolne z wyrażeń jest niezerowe.

Wyrażenia mają 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. Weźmy następujące 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ą:

Wynikiem funkcji length jest liczba cyfr znaczących w wyrażeniu.
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.
Wynikiem funkcji scale jest liczba cyfr po kropce dziesiętnej w wyrażeniu będącym jej parametrem.
Wynikiem funkcji sqrt jest pierwiastek kwadratowy z wyrażenia. Jeżeli wyrażenie ma wartość ujemną, to generowany jest błąd wykonania.

Statements (as in most algebraic languages) provide the sequencing of expression evaluation. In bc statements are executed "as soon as possible". Execution happens when a newline in encountered and there is one or more complete statements. Due to this immediate execution, newlines are very important in bc. In fact, both a semicolon and a newline are used as statement separators. An improperly placed newline will cause a syntax error. Because newlines are statement separators, it is possible to hide a newline by using the backslash character. The sequence "\<nl>", where <nl> is the newline appears to bc as whitespace instead of a newline. A statement list is a series of statements separated by semicolons and newlines. The following is a list of bc statements and what they do: (Things enclosed in brackets ([]) are optional parts of the statement.)

This statement does one of two things. If the expression starts with "<variable> <assignment> ...", it is considered to be an assignment statement. If the expression is not an assignment statement, the expression is evaluated and printed to the output. After the number is printed, a newline is printed. For example, "a=1" is an assignment statement and "(a=1)" is an expression that has an embedded assignment. All numbers that are printed are printed in the base specified by the variable obase. The valid values for obase are 2 through BC_BASE_MAX. (See the section LIMITS.) For bases 2 through 16, the usual method of writing numbers is used. For bases greater than 16, bc uses a multi-character digit method of printing the numbers where each higher base digit is printed as a base 10 number. The multi-character digits are separated by spaces. Each digit contains the number of characters required to represent the base ten value of "obase-1". Since numbers are of arbitrary precision, some numbers may not be printable on a single output line. These long numbers will be split across lines using the "\" as the last character on a line. The maximum number of characters printed per line is 70. Due to the interactive nature of bc, printing a number causes the side effect of assigning the printed value to the special variable last. This allows the user to recover the last value printed without having to retype the expression that printed the number. Assigning to last is valid and will overwrite the last printed value with the assigned value. The newly assigned value will remain until the next number is printed or another value is assigned to last. (Some installations may allow the use of a single period (.) which is not part of a number as a short hand notation for 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.
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” (wysunięcie 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.
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).
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).
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;
}
Instrukcja ta powoduje wymuszone zakończenie ostatniej obejmującej ją instrukcji while lub for.
Instrukcja continue (rozszerzenie) powoduje rozpoczęcie kolejnej iteracji przez ostatnią obejmującą ją instrukcję for.
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.
Zwraca wartość zero jako wynik funkcji. (Patrz sekcja dotycząca funkcji).
Zwraca wartość wyrażenia jako wynik funkcji. (Patrz sekcja dotycząca funkcji). Nawiasy nie są wymagane, co jest rozszerzeniem GNU bc.

Te instrukcje nie są instrukcjami w tradycyjnym sensie tego terminu. Nie są one instrukcjami wykonywanymi. Ich funkcja jest wykonywana podczas „kompilacji”.

Wypisuje lokalne ograniczenia narzucone przez lokalna wersję bc. Jest to rozszerzenie.
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) quitr” spowoduje zakończenie pracy bc.
Wypisuje dłuższą notkę na temat gwarancji. Jest to rozszerzenie.

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 zero lub więcej jej parametrów przez podanie ich nazw rozdzielonych przecinkami. Liczby są jedynymi parametrami wywoływanymi przez wartość. 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 wartość. Ponieważ definicje funkcji są dynamiczne, w trakcie wywoływania funkcji sprawdzana jest liczba i typy jej parametrów. Niezgodność 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 ( wyrażenie )”, 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.

Several extensions have been added to functions. First, the format of the definition has been slightly relaxed. The standard requires the opening brace be on the same line as the define keyword and all other parts must be on following lines. This version of bc will allow any number of newlines before and after the opening brace of the function. For example, the following definitions are valid.


define d (n) { return (2*n); }
define d (n)
  { return (2*n); }

Funkcje mogą być zdefiniowane jako void. Funkcja void nie zwraca wartości, więc nie może być używana w miejscach, które wymagają wartości. Po wywołaniu funkcja void nie produkuje żadnego wyjścia. Słowo kluczowe void występuje pomiędzy słowem kluczowym define a nazwą funkcji. Na przykład prosimy rozważyć poniższy skrypt:


define py (y) { print "--->", y, "<---", "\n"; }
define void px (x) { print "--->", x, "<---", "\n"; }
py(1)
--->1<---
0
px(1)
--->1<---
Since py is not a void function, the call of py(1) prints the desired output and then prints a second line that is the value of the function. Since the value of a function that is not given an explicit return statement is zero, the zero is printed. For px(1), no zero is printed because the function is a void function.

Także dodano wywoływanie tablic przez zmienną. Aby zadeklarować wywołanie przez zmienną tablicową, należy zadeklarować parametr tablicowy w definicji funkcji jako „*nazwa[]”. Wywołanie funkcji jest takie samo, jak w przypadku wywołania przez wartość.

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:

Sinus x, x podawany jest w radianach.
Cosinus x, x w radianach.
Arcus tangens x; arcus tangens zwraca radiany.
Logarytm naturalny z x.
Funkcja wykładnicza - e do potęgi x.
Funkcja Bessela rzędu n (całkowitego) z argumentem x.

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
/* Uses the fact that e^x = (e^(x/2))^2
   When x is small enough, we use the series:
     e^x = 1 + x + x^2/2! + x^3/3! + ...
*/
define e(x) {
  auto  a, d, e, f, i, m, v, z
  /* Check the sign of x. */
  if (x<0) {
    m = 1
    x = -x
  }
  /* Precondition x. */
  z = scale;
  scale = 4 + z + .44*x;
  while (x > 1) {
    f += 1;
    x /= 2;
  }
  /* Initialize the variables. */
  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 "\nCheck book program!\n"
print "  Remember, deposits are negative transactions.\n"
print "  Exit by a 0 transaction.\n\n"
print "Initial balance? "; bal = read()
bal /= 1
print "\n"
while (1) {
  "current balance = "; bal
  "transaction? "; 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);
}

GNU bc może zostać skompilowany (przez 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 zawiera 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.

This version of bc was implemented from the POSIX P1003.2/D11 draft and contains several differences and extensions relative to the draft and traditional implementations. It is not implemented in the traditional way using dc(1). This version is a single process which parses and runs a byte code translation of the program. There is an "undocumented" option (-c) that causes the program to output the byte code to the standard output instead of running it. It was mainly used for debugging the parser and preparing the math library.

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ń.

Niniejsza wersja nie spełnia standardu POSIX przetwarzania zmiennej środowiska LANG i wszystkich zmiennych środowiska rozpoczynających się na LC_.
Tradycyjny i POSIXowy bc zawierają 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 znakowe
Łańcuchy nie mogą zawierać znaków NUL. POSIX stwierdza, że wszystkie znaki muszą być zawarte w łańcuchach.
POSIX bc nie zawiera zmiennej last. Niektóre implementacje bc używają kropki (.) w podobny sposób.
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).
POSIX bc nie zawiera klauzuli else.
POSIX bc wymaga, by w instrukcji for występowały wszystkie wyrażenia.
&&, ||, !
POSIX bc nie zawiera operatorów logicznych.
POSIX bc nie zawiera funkcji read.
POSIX bc nie zawiera instrukcji print.
POSIX bc nie zawiera instrukcji continue.
POSIX bc wymaga nawiasów wokół zwracanego wyrażenia.
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 mają jedynie wywołanie parametrów tablicowych przez wartość.
POSIX bc wymaga, by nawias otwierający był w tym samym wierszu, co słowo kluczowe define, instrukcja auto natomiast 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.
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.
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
ma 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.

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.

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).

The maximum output base is at least 10^9. The maximum input base is 16.
Obecnie ustawione jest arbitralne ograniczenie do 65535 (w wersji rozpowszechnianej). Twoja instalacja może być inna.
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.
Maksymalnie w łańcuchu może wystąpić INT_MAX znaków.
Wartość wykładnika w operacji potęgowania (^) ograniczona jest do LONG_MAX.
nazwy zmiennych
Obecnie nie może być więcej niż 32767 unikatowych nazw w każdym z rodzajów: zmiennych prostych, tablic i funkcji.

bc przetwarza następujące zmienne środowiska:

To samo, co opcja -s. Tryb zgodności z POSIX.
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.
Powinna to być liczba całkowita (integer) podająca liczbę znaków w wierszu wynikowym. Obejmuje ona znaki odwrotnego ukośnika i nowej linii dla długich liczb. Jako rozszerzenie GNU wartość zero wyłącza wieloliniowe wyjście. Jakakolwiek inna wartość mniejsza od 3 ustawia długość linii na 70.

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.

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. Proszę się upewnić, że pole tematu wiadomości zawiera gdzieś słowo „bc”.

Philip A. Nelson
philnelson@acm.org

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.

Autorami polskiego tłumaczenia niniejszej strony podręcznika są: Wojtek Kotwica <wkotwica@post.pl>, Robert Luberda <robert@debian.org> i Michał Kułach <michal.kulach@gmail.com>

Niniejsze tłumaczenie jest wolną dokumentacją. Bliższe informacje o warunkach licencji można uzyskać zapoznając się z GNU General Public License w wersji 3 lub nowszej. Nie przyjmuje się ŻADNEJ ODPOWIEDZIALNOŚCI.

Błędy w tłumaczeniu strony podręcznika prosimy zgłaszać na adres listy dyskusyjnej manpages-pl-list@lists.sourceforge.net.

5 stycznia 2025 r. Projekt GNU