| bc(1) | General Commands Manual | bc(1) |
bc - un limbaj de calcul cu precizie arbitrară
bc [ -hlwsqv ] [opțiuni-lungi] [ fișier ... ]
bc este un limbaj care acceptă numere cu precizie arbitrară cu execuție interactivă a instrucțiunilor. Există unele asemănări în sintaxă cu limbajul de programare C. O bibliotecă de matematică standard este disponibilă prin opțiune de linie de comandă. Dacă se solicită, biblioteca de matematică este definită înainte de procesarea oricăror fișiere. bc începe prin procesarea codului din toate fișierele enumerate în linia de comandă, în ordinea enumerată. După ce toate fișierele au fost procesate, bc citește de la intrarea standard. Tot codul este executat pe măsură ce este citit; (dacă un fișier conține o comandă de oprire a procesorului, bc nu va citi niciodată de la intrarea standard).
Această versiune a bc conține mai multe extensii care depășesc implementările bc tradiționale și proiectul de standard POSIX. Opțiunile din linia de comandă pot face ca aceste extensii să afișeze un avertisment sau să fie respinse. Acest document descrie limbajul acceptat de acest procesor. Extensiile vor fi identificate ca atare.
Cel mai de bază element în bc este numărul. Numerele sunt numere cu precizie arbitrară. Această precizie este atât în partea întreagă, cât și în partea fracționară. Toate numerele sunt reprezentate intern în zecimal și toate calculele sunt efectuate în zecimal; (această versiune trunchiază rezultatele operațiilor de împărțire și multiplicare). Există două atribute ale numerelor, lungimea și scala. Lungimea este numărul total de cifre zecimale utilizate de bc pentru a reprezenta un număr, iar scala este numărul total de cifre zecimale după punctul zecimal. De exemplu:
.000001 are o lungime de 6 și o scală de 6.
1935.000 are o lungime de 7 și o scală de 3.
Numerele sunt stocate în două tipuri de variabile, variabile simple și matrice. Atât variabilele simple, cât și variabilele matrice sunt denumite. Numele încep cu o literă urmată de orice număr de litere, cifre și liniuțe de subliniere. Toate literele trebuie să fie în minuscule. Numele alfanumerice complete sunt o extensie; în bc POSIX toate numele sunt formate dintr-o singură literă minusculă). Tipul de variabilă este clar în funcție de context, deoarece toate numele variabilelor de tip matrice vor fi urmate de paranteze drepte ([]).
Există patru variabile speciale, scale, ibase, obase, și last. scale definește modul în care unele operații utilizează cifrele după punctul zecimal. Valoarea implicită a lui scale este 0. ibase și obase definesc baza de conversie pentru numerele de intrare și ieșire. Valoarea implicită atât pentru intrare, cât și pentru ieșire este baza 10. last (o extensie) este o variabilă care are valoarea ultimului număr afișat. Acestea vor fi discutate mai detaliat acolo unde este cazul. Toate aceste variabile pot avea valori atribuite, precum și utilizate în expresii.
Comentariile din bc încep cu caracterele /* și se termină cu caracterele */. Comentariile pot începe oriunde și apar ca un singur spațiu în textul de intrare; (acest lucru face ca comentariile să delimiteze alte elemente de intrare - de exemplu, un comentariu nu poate fi găsit în mijlocul unui nume de variabilă). Comentariile includ orice linii noi (sfârșit de linie) între începutul și sfârșitul comentariului.
Pentru a oferi suport pentru utilizarea scripturilor pentru bc, a fost adăugat un comentariu pe o singură linie ca extensie. Un comentariu pe o singură linie începe la un caracter # și continuă până la următorul capăt de linie. Caracterul de sfârșit de linie nu face parte din comentariu și este procesat în mod normal.
Numerele sunt manipulate prin expresii și instrucțiuni. Deoarece limbajul a fost conceput pentru a fi interactiv, instrucțiunile și expresiile sunt executate cât mai curând posibil. Nu există un program „principal”. În schimb, codul este executat pe măsură ce este întâlnit; (funcțiile, discutate în detaliu mai târziu, sunt definite atunci când sunt întâlnite).
O expresie simplă este doar o constantă. bc convertește constantele în numere zecimale interne folosind baza de intrare curentă, specificată de variabila ibase.; (există o excepție în funcții). Valorile valide pentru ibase sunt de la 2 la 36; (bazele mai mari de 16 sunt o extensie). Atribuirea unei valori în afara acestui interval pentru ibase va avea ca rezultat o valoare de 2 sau 36. Numerele de intrare pot conține caracterele 0-9 și A-Z. - Notă: Acestea trebuie să fie în majuscule. Literele minuscule sunt nume de variabile. - Numerele cu o singură cifră au întotdeauna valoarea cifrei indiferent de valoarea lui ibase, (de exemplu, A = 10.) Pentru numerele cu mai multe cifre, bc schimbă toate cifrele de intrare mai mari sau egale cu ibase la valoarea ibase-1. Acest lucru face ca numărul ZZZ să fie întotdeauna cel mai mare număr de 3 cifre din baza de intrare.
Expresiile complete sunt similare cu multe alte limbaje de nivel înalt. Deoarece există un singur tip de număr, nu există reguli pentru amestecarea tipurilor. În schimb, există reguli privind scala expresiilor. Fiecare expresie are o scală. Aceasta este derivată din scala numerelor originale, operația efectuată și, în multe cazuri, valoarea variabilei scale. Valorile legale ale variabilei scale sunt de la 0 la numărul maxim reprezentabil de un număr întreg C.
În următoarele descrieri ale expresiilor permise, „expr” se referă la o expresie completă, iar „var” se referă la o variabilă simplă sau la o matrice. O variabilă simplă este doar o
Expresiile relaționale sunt un tip special de expresie care evaluează întotdeauna la 0 sau 1, 0 dacă relația este falsă și 1 dacă relația este adevărată. Acestea pot apărea în orice expresie permisă; (bc POSIX impune ca expresiile relaționale să fie utilizate numai în declarațiile if, while și for și ca numai un test relațional să poată fi efectuat în acestea). Operatorii relaționali sunt
Operațiile booleene sunt, de asemenea, valabile; (bc POSIX NU are operații booleene). Rezultatul tuturor operațiilor booleene sunt 0 și 1 (pentru fals (false) și adevărat (true)) ca în expresiile relaționale. Operatorii booleeni sunt:
Precedența expresiilor este după cum urmează: (de la cea mai mică la cea mai mare)
operator ||, asociativ la stânga operator &&, asociativ la stânga operator !, neasociativ operatori relaționali, asociativi la stânga operator de atribuire, asociativ la dreapta operatori + și -, asociativ la stânga operatori *, / și %, asociativ la stânga operator ^, asociativ la dreapta operator unar -, neasociativ operatori ++ și --, neasociativi
Această precedență a fost aleasă astfel încât programele bc conforme cu POSIX să ruleze corect. Acest lucru va face ca utilizarea operatorilor logici și relaționali să aibă un comportament neobișnuit atunci când sunt utilizați cu expresii de atribuire. Luați în considerare expresia:
Majoritatea programatorilor C ar presupune că acest lucru ar atribui rezultatul „3 < 5” (valoarea 1) variabilei „a”. Ceea ce face acest lucru în bc este să atribuie valoarea 3 variabilei „a” și apoi să compare 3 cu 5. Cel mai bine este să folosiți paranteze atunci când utilizați operatorii relaționali și logici cu operatorii de atribuire.
Mai există câteva expresii speciale care sunt furnizate în bc. Acestea au de-a face cu funcții definite de utilizator și funcții standard. Toate apar ca „nume(parametri)”. Consultați secțiunea privind funcțiile, pentru funcțiile definite de utilizator. Funcțiile standard sunt:
Instrucțiunile (ca în majoritatea limbajelor algebrice) asigură secvența de evaluare a expresiilor. În bc instrucțiunile sunt executate „de îndată ce este posibil”. Execuția are loc atunci când este întâlnită o linie nouă și există una sau mai multe instrucțiuni complete. Datorită acestei execuții imediate, liniile noi sunt foarte importante în bc. De fapt, atât punctul și virgula, cât și linia nouă sunt utilizate ca separatoare de instrucțiuni. O linie nouă plasată necorespunzător va cauza o eroare de sintaxă. Deoarece liniile noi sunt separatoare de instrucțiuni, este posibil să se ascundă o linie nouă prin utilizarea caracterului de bară oblică inversă. Secvența „\<nl>”, unde <nl> este linia nouă, apare pentru bc ca spațiu alb în loc de o linie nouă. O listă de instrucțiuni este o serie de instrucțiuni separate prin punct și virgulă și linii noi. Următoarea este o listă de instrucțiuni bc și ce fac acestea: (Lucrurile incluse în paranteze ([]) sunt părți opționale ale instrucțiunii).
expresie1;
while (expresie2) {
declarație
expresie3;
}
Aceste instrucțiuni nu sunt instrucțiuni în sensul tradițional. Ele nu sunt instrucțiuni executate. Funcția lor este îndeplinită la momentul „compilării”.
Funcțiile oferă o metodă de definire a unui calcul care poate fi executat ulterior. Funcțiile din bc calculează întotdeauna o valoare și o returnează apelantului. Definițiile funcțiilor sunt „dinamice” în sensul că o funcție este nedefinită până când o definiție este întâlnită în intrare. Acea definiție este apoi utilizată până când este întâlnită o altă funcție de definiție pentru același nume. Noua definiție înlocuiește atunci vechea definiție. O funcție este definită după cum urmează:
define nume( parametri ) { linie nouă listă_auto listă_de_instrucțiuni }
Un apel de funcție este doar o expresie de forma „nume(parametri)”.
Parametrii sunt numere sau matrici (o extensie). În definiția funcției, zero sau mai mulți parametri sunt definiți prin enumerarea numelor lor separate prin virgulă. Toți parametrii sunt parametrii de apel prin valoare. Matricele sunt specificate în definiția parametrilor prin notația „nume[]”. În apelul funcției, parametrii efectivi sunt expresii complete pentru parametrii numerici. Pentru pasarea matricelor se utilizează aceeași notație ca și pentru definirea parametrilor matricelor. Matricea numită este pasată prin valoare către funcție. Deoarece definițiile funcțiilor sunt dinamice, numărul și tipul parametrilor sunt verificate atunci când se apelează o funcție. Orice neconcordanță în ceea ce privește numărul sau tipurile de parametri va provoca o eroare în timpul execuției. O eroare de execuție va apărea și în cazul apelării unei funcții nedefinite.
auto_list este o listă opțională de variabile care sunt pentru utilizare „locală”. Sintaxa listei auto (dacă este prezentă) este „auto nume, ... ;”. (Punctul și virgula este opțional.) Fiecare nume este numele unei variabile auto. Matricele pot fi specificate prin utilizarea aceleiași notații ca în cazul parametrilor. Aceste variabile au valorile lor plasate pe o stivă la începutul funcției. Variabilele sunt apoi inițializate la zero și utilizate pe parcursul execuției funcției. La ieșirea din funcție, aceste variabile sunt scoase, astfel încât valoarea inițială (la momentul apelului funcției) a acestor variabile să fie restaurată. Parametrii sunt de fapt variabile automate care sunt inițializate la o valoare furnizată în apelul funcției. Variabilele automate sunt diferite de variabilele locale tradiționale deoarece, dacă funcția A apelează funcția B, B poate accesa variabilele automate ale funcției A folosind doar același nume, cu excepția cazului în care funcția B le-a numit variabile automate. Datorită faptului că variabilele automate și parametrii sunt plasați pe o stivă, bc acceptă funcții recursive.
Corpul funcției este o listă de instrucțiuni bc. Din nou, instrucțiunile sunt separate prin punct și virgulă sau linii noi. Instrucțiunile return determină terminarea unei funcții și returnarea unei valori. Există două versiuni ale instrucțiunii return. Prima formă, „return”, returnează valoarea 0 la expresia apelantă. A doua formă, „return ( expresie )”, calculează valoarea expresiei și returnează această valoare expresiei apelante. Există un „return (0)” implicit la sfârșitul fiecărei funcții. Acest lucru permite unei funcții să se încheie și să returneze 0 fără o instrucțiune de returnare explicită.
Funcțiile modifică, de asemenea, utilizarea variabilei ibase. Toate constantele din corpul funcției vor fi convertite folosind valoarea lui ibase la momentul apelului funcției. Modificările lui ibase vor fi ignorate în timpul executării funcției, cu excepția funcției standard read, care va utiliza întotdeauna valoarea curentă a lui ibase pentru conversia numerelor.
Funcțiilor le-au fost adăugate mai multe extensii. În primul rând, formatul definiției a fost ușor relaxat. Standardul cere ca acolada de deschidere să fie pe aceeași linie cu cuvântul-cheie define și toate celelalte părți trebuie să fie pe liniile următoare. Această versiune a bc va permite orice număr de linii noi înainte și după acolada de deschidere a funcției. De exemplu, următoarele definiții sunt valabile.
define d (n) { return (2*n); } define d (n) { return (2*n); }
Funcțiile pot fi definite ca void. O funcție vidă nu returnează nicio valoare și, prin urmare, nu poate fi utilizată în niciun loc care necesită o valoare. O funcție vidă nu produce niciun rezultat atunci când este apelată singură pe o linie de intrare. Cuvântul cheie void este plasat între cuvântul cheie define și numele funcției. De exemplu, luați în considerare următoarea sesiune.
define py (y) { print "--->", y, "<---", "\n"; } define void px (x) { print "--->", x, "<---", "\n"; } py(1) --->1<--- 0 px(1) --->1<---
De asemenea, a fost adăugat apelul prin variabilă pentru matrice. Pentru a declara o matrice cu apel prin variabilă, declarația parametrului matricei în definiția funcției arată ca „*nume[]”. Apelul la funcție rămâne același ca în cazul apelului prin valoare a matricelor.
Dacă bc este invocat cu opțiunea -l, o bibliotecă de matematică este preîncărcată, iar scala implicită este fixată la 20. Funcțiile matematice își vor calcula rezultatele la scala stabilită în momentul apelării lor. Biblioteca de matematică definește următoarele funcții:
În /bin/sh, următorul text va atribui valoarea „pi” variabilei shell pi.
The following is the definition of the exponential function used in the math library. This function is written in POSIX bc.
scale = 20 /* Folosește faptul că e^x = (e^(x/2))^2 Când x este suficient de mic, se folosește seria: e^x = 1 + x + x^2/2! + x^3/3! + ... */ define e(x) { auto a, d, e, f, i, m, v, z /* Verifică semnul lui x. */ if (x<0) { m = 1 x = -x } /* Precondiție x. */ z = scale; scale = 4 + z + .44*x; while (x > 1) { f += 1; x /= 2; } /* Inițializează variabilele. */ 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 } }
În continuare este prezentat codul care utilizează caracteristicile extinse ale bc pentru a implementa un program simplu de calculare a soldurilor carnetului de cecuri. Acest program este cel mai bine să fie păstrat într-un fișier pentru a putea fi utilizat de mai multe ori fără a fi nevoie să îl rescrieți la fiecare utilizare.
scale=2 print "\nProgramul registrului de balanțe!\n” print „ Țineți minte, depozitele sunt tranzacții negative.\n” print „ Ieșire printr-o tranzacție 0.\n\n" print "Soldul inițial? "; bal = read() bal /= 1 print "\n" while (1) { "current balance = "; bal "transaction? "; trans = read() if (trans == 0) break; bal -= trans bal /= 1 } quit
Următoarea este definiția funcției factoriale recursive.
define f (x) { if (x <= 1) return (1); return (f(x-1) * x); }
bc GNU poate fi compilat (prin intermediul unei opțiuni configure) pentru a utiliza biblioteca editorului de intrare GNU readline sau biblioteca BSD libedit. Acest lucru permite utilizatorului să editeze liniile înainte de a le trimite la bc. De asemenea, permite un istoric al liniilor tastate anterior. Când această opțiune este selectată, bc mai are o variabilă specială. Această variabilă specială, history este numărul de linii de istoric reținute. Pentru readline, o valoare de -1 înseamnă că se păstrează un număr nelimitat de linii de istoric. Stabilirea valorii history la un număr pozitiv limitează numărul de linii de istoric la numărul dat. Valoarea 0 dezactivează funcția de istoric. Valoarea implicită este 100. Pentru mai multe informații, citiți manualele de utilizare pentru bibliotecile GNU readline, history și BSD libedit. Nu se pot activa în același timp readline și libedit.
Această versiune a bc a fost implementată pornind de la proiectul POSIX P1003.2/D11 și conține mai multe diferențe și extensii în raport cu proiectul și implementările tradiționale. Aceasta nu este implementată în mod tradițional folosind dc(1). Această versiune este un proces unic care analizează și execută o traducere a codului de octeți al programului. Există o opțiune „nedocumentată” (-c) care face ca programul să trimită codul de octeți la ieșirea standard în loc să îl execute. Aceasta a fost utilizată în principal pentru depanarea analizorului și pregătirea bibliotecii de matematică.
O sursă majoră de diferențe este reprezentată de extensii, atunci când o caracteristică este extinsă pentru a adăuga mai multe funcționalități și de adăugiri, atunci când sunt adăugate noi caracteristici. Următoarea este lista de diferențe și extensii.
a = 1 b = 2
{ a = 1
b = 2 }
are un singur bloc de execuție. Orice eroare în timp de execuție va încheia execuția blocului de execuție curent. Un avertisment de timp de execuție nu va încheia blocul de execuție curent.
Următoarele sunt limitele existente în prezent pentru acest procesor bc. Este posibil ca unele dintre ele să fi fost modificate de o instalare. Utilizați declarația limits pentru a vedea valorile actuale.
Următoarele variabile de mediu sunt prelucrate de bc:
Dacă un fișier din linia de comandă nu poate fi deschis, bc va raporta că fișierul nu este disponibil și se va încheia. De asemenea, există diagnostice de compilare și de execuție care ar trebui să se explice de la sine.
Recuperarea erorilor nu este încă foarte bună.
Trimiteți rapoartele de erori prin poștă electronică la adresa bug-bc@gnu.org. Asigurați-vă că includeți cuvântul „bc” undeva în câmpul „Subiect:”.
Philip A. Nelson philnelson@acm.org
Autorul dorește să îi mulțumească lui Steve Sommars (Steve.Sommars@att.com) pentru ajutorul său extins în testarea implementării. Au fost oferite multe sugestii excelente. Acesta este un produs mult mai bun datorită implicării sale.
Traducerea în limba română a acestui manual a fost făcută de Remus-Gabriel Chelu <remusgabriel.chelu@disroot.org>
Această traducere este documentație gratuită; citiți Licența publică generală GNU Versiunea 3 sau o versiune ulterioară cu privire la condiții privind drepturile de autor. NU se asumă NICIO RESPONSABILITATE.
Dacă găsiți erori în traducerea acestui manual, vă rugăm să trimiteți un e-mail la translation-team-ro@lists.sourceforge.net.
| 11 iunie 2006 | Proiectul GNU |