Programowanie w systemie UNIX/bc

Z Wikibooks, biblioteki wolnych podręczników.

bc (od ang. basic calculator) jest to język programowania umożliwiający:

  • operowanie liczbami w dowolnych systemach liczbowych (wejście możliwe w systemie maksymalnie szesnastkowym, wyjście w dowolnie dużym), ale nie w formacie naukowym[1]
  • operowanie liczbami dowolnej precyzji (zarówno przed, jak i po przecinku)
  • wykonywanie skryptów
  • wczytywanie danych z pliku lub standardowego wejścia. Pozwala to na użycie potoku (ang. pipe)

bc jest preprocesorem dla dc[2]

Podstawowe operacje[edytuj]

Uruchomianie[edytuj]

w konsoli wpisujemy

bc

Jest to podstawowy sposób uruchomienia. Standardowo liczba miejsc po przecinku (ang. scale) jest ustawiona na 0. Nie ładuje biblioteki standardowej.

Uruchomienie z opcją l :

  • powoduje załadowanie przy uruchomieniu biblioteki standardowej, zawierającą np. funkcje trygonometryczne
  • ustawia liczbę miejsc po przecinku dla dzielenia (ang. scale) na 20 zamiast domyślnego 0
  • jest równoważna opcji --mathlib; ładuje standardową bibliotekę matematyczną[3]
bc -l

Pełna składnia:

bc [-hlwsqv] [długie_opcje] [plik...]


W ten sposób możemy wczytać skrypty bc

Kończenie pracy[edytuj]

W celu zakończenia pracy wpisujemy w bc:

quit

albo sekwencje klawiszy:

control-D

Ustawienia[edytuj]

limits[edytuj]

Za pomocą komendy:[4]

limits

sprawdzamy aktualne ustawienia:

BC_BASE_MAX     = 2147483647
BC_DIM_MAX      = 16777215
BC_SCALE_MAX    = 2147483647
BC_STRING_MAX   = 2147483647
MAX Exponent    = 9223372036854775807
Number of vars  = 32767

ibase i obase[edytuj]

Są to 2 specjalne zmienne (ang. special variables) określające podstawę (ang. base) liczb dla wejścia (ibase) i wyjścia (obase).

Najpierw sprawdźmy domyślne ustawienie:

ibase
10
obase
10

Zakres warto sci dla obase wynosi od 2 do 999 a dla ibase od 2 do 16.

Dzięki temu możemy wykonywać konwersje.

scale[edytuj]

Możemy zmienić poprzez:

  • uruchomienie (bc lub bc -l)
  • ręczne ustawienie: scale= 20
  • ustawienie w pliku .bashrc
    • w pliku .bashrc w katalogu domowym dodać BC_ENV_ARGS=~/.bc
    • potem export BC_ENV_ARGS
    • utworzyć plik .bc w katalogu domowym z jedną linią scale=2[5]

BC_LINE_LENGTH[edytuj]

Długość linii wydruku jest określona przez zmienną BC_LINE_LENGTH. Standardowo zmienna nie jest określona.

Przykład:

echo "scale=100;last=10;8/(1+(1/3))" | bc 

powoduje:

6.000000000000000000000000000000000000000000000000000000000000000000\
0000000000000000000000000000000001

W celu zmiany tego zachowania:

 export BC_LINE_LENGTH=105

i ponownie

echo "scale=100;last=10;8/(1+(1/3))"|bc

otrzymujemy:

6.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001

BC_ENV_ARGS[edytuj]

Tryby pracy[edytuj]

Interaktywny[edytuj]

bc[edytuj]

Uruchamiamy bc poprzez wpisanie w konsoli:

bc

otrzymujemy:

bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 

Przykładowe obliczenie:

2^5-1

i wynik:

31

Kończymy pracę lub wprowadzamy nowe obliczenia.

Jeśli chcemy mieś większą dokładność to uruchamiamy z parametrem

bc -l
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.

Sprawdzamy jaka jest dokładność:

scale 

wynik:

20

Wprowadzamy obliczenia:

  
33877456965431938318210482471113262183356704085033125021829876006886584214655562
/
237142198758023568227473377297792835283496928595231875152809132048206089502588927

wynik

.14285714285714285714

Zwiększamy dokładność:

scale=300

Ponownie obliczamy:

33877456965431938318210482471113262183356704085033125021829876006886584214655562
/
237142198758023568227473377297792835283496928595231875152809132048206089502588927

Wynik:

.1428571428571428571428571428571428571428571428571428571428571428571
42857142857147074022034435066432596572477650864745941127410090260162
88824806718611485924504671182507728691759096030983169039376702287127
38977340379914830920623570643668473851880233962854802649343258544237
37842209566161182966664275147

z poziomu bash'a[edytuj]

Z poziomu bash'a przesyłamy dane do bc korzystając z potoku:

echo '57+43' | bc

otrzymujemy wynik:

100

lub inny sposób: [5]

bc <<< 56.8+77.7

otrzymujemy:

134.5

Inny przykład:

bc -l <<< '10.5 / 1'
10.50000000000000000000


Inna metoda:

cru=$(echo $center_im+$r | bc -l)

Skryptowy[edytuj]

Bash'a[edytuj]

Skrypt Bash'a wysyła dane do bc. Odbiera wyniki i zapisuje je do zmiennych (num i den). Wyniki obliczeń z wykorzystaniem tych zmiennych zapisuje do pliku tekstowego[6]


Tutaj

  • używamy backtick, aby uruchomić polecenie bc i przypisać dane wyjściowe do zmiennej
  • W części dotyczącej opcji ustawiamy zmienne takie jak skala
  • Operacje matematyczne są wykonywane w części wyrażeniowej
variable=`echo "options; expression" | bc`

Przykład

add=`echo "scale=4; $num1+$num2" | bc`

Cały skrypt:

#!/bin/bash
# based on the code by Claude Heiland-Allen http://mathr.co.uk/blog/
rot=34
den=$(echo "2^${rot}-1" | bc)
for i in $(seq 0 $((rot-1)))
do
  num=$(echo "2^${i}" | bc)
  echo  "${num}/${den}"
  echo
  echo
done > "${rot}.txt"

bc[edytuj]

Przykłady[edytuj]

liczby zmiennoprzecinkowe w bash[edytuj]

dzięki bc możemy używać liczb zmiennoprzecinkowych w powłoce, także w skryptach[7][8]

   
#!/bin/bash 
a=1.12
b=0.34
c=$(echo "$a * $b"|bc -l)
echo "$c"

Wynik :

  
b=0.34
c=$(echo "$a * $b"|bc -l)
echo "$c"
.3808

Kolejność wykonywania działań[edytuj]

1/3*2
.66666666666666666666
1/(3*2)
.16666666666666666666

Komentarz dzielenie i mnożenia mają ten sam poziom[9] [10] więc wykonuje się je w kolejności od lewej do prawej

Może to powodować błąd w następującej sytuacji:

1/1*10^-6
.00000100000000000000
1/10^-6
1000000.00000000000000000000

Dzielenie[edytuj]

echo 'scale=25;57/43' | bc

wynik:

1.3255813953488372093023255

Konwersje[edytuj]

Zmiana e na 10[edytuj]

Jak przekształcić 1.0e-2 na 1.0*10^-2?[11]

radius="1.0e-2.0"
rim=`echo ${radius} | sed -e 's/[eE]+*/\\*10\\^/'` 
echo $rim

wynik:

1.0*10^-2.0

zmiana podstawy[edytuj]

Przekształcamy dziesiętną liczbę 12 (ibase = 10) na liczbę binarną (obase = 2)

$ echo 'obase=2;12' | bc

otrzymujemy:

1100



bc
bc 1.07.1
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006, 2008, 2012-2017 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
obase=2
scale=300 
3/14
.0011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011011010
scale=100
3.14159265358979323846264338327950288419716939937510
11.00100100001111110110101010001000100001011010001100001000110100110001001100011001100010100010111000000011011100000111001101000100101001000000100100111000001000100010011

zmiana typu[edytuj]

Zmiennoprzecinkowa do całkowitej (obcinanie = trunc):

echo '(4.2-1.3) / 1' | bc

wynik:

2

Nie działa dla liczb ujemnych i gdy scale > 0[12]

Pomoc[edytuj]

Podręcznik offline[13] w aktualnej wersji po polsku (ang. manual) otwiera się po wpisaniu w konsoli polecenia:

man bc

lub:

info bc

Zamykamy podręcznik klawiszem q.

Pomoc online jest zwykle nieaktualna [14]


Wersja:

 bc -v

otrzymujemy:

 bc 1.06.95
 Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.

Podobna informacja jest na 1 stronie podręcznika:

WERSJA Niniejszy podręcznik opisuje GNU bc w wersji 1.06.

Zobacz również[edytuj]

Źródła[edytuj]

  1. Stackoverflow: How to get bc to handle numbers in scientific (aka exponential) notation?
  2. command-line calculations using bc, by Rob Newcater
  3. stackoverflow question: how-can-i-compare-two-floating-point-numbers-in-bash
  4. bc - limits
  5. 5,0 5,1 Command line calculator, bc. Tip by Mark B
  6. tutorialsandyou : bash-bc
  7. linux journal : floating-point-math-bash by Mitch Frazier on July 30, 2008
  8. stackoverflow question: how-can-i-compare-two-floating-point-numbers-in-bash
  9. bc manual: Precedence
  10. Kolejność wykonywania działań w Wikipedii
  11. How to get bc to handle numbers in scientific (aka exponential) notation?
  12. Stackoverflow : bc truncate floating point number
  13. man (Unix)
  14. bc doc at opengroup