bc exercise

Visit the phodd.net GNU bc page to get a file full of bc functions. We want to put it in a working directory and unzip it:

mkdir  ~/bc-temp
cd  bc-temp
wget  http://phodd.net/gnu-bc/phodd.net-gnu-bc-201302202200+html.zip
unzip  phodd.net-gnu-bc-phodd.net-gnu-bc-201302202200+html.zip
cd  code
ls

Each of the approximately 40 files you see, with .bc extensions, holds a number of functions scripted/written in bc. They are well documented on the web page. You use such a file by naming it as a command-line argument when invoking bc. Then, when bc itself loads into memory it also loads in the functions in that file. You can then use those functions in bc. In a sense it's a function library.

The funcs.bc file contains, among others, functions  pow( ) and gcd( ). Find their documentation on the web page, then find their code within funcs.bc. Run bc, including funcs.c, then interactively try the functions:

bc  -l  funcs.bc
pow(3,4)
gcd(125,20)
quit


pow( ) gives you 3 to the 4th power; gcd( ) gives the greatest divisor common to 125 and 20. If you had not named funcs.bc on the bc command line these would have been unavailable. Doing so loaded them into memory. Their purpose and operation are clear, their code is a little complicated. Note the syntax. It's bc, not shell.

Another file is thermometer.bc. In it, look at the conversion functions. They are quite simple. Invoke bc with thermometer.bc, then invoke farenheit_to_celcius( ) with 212 as argument.

Here are a couple of relatively simple math functions:


/* sign of an integer a */
/* sign(a)=1,-1,0, according as a>0,a<0,a=0 */
define sign(a){
if(a>0) return(1)
if(a<0) return(-1)
return(0)
}

/* absolute value of an integer n */
define abs(n){
if(n>=0) return(n)
return(-n)
}

You can put these at bc's disposal different ways. First, run bc. In interactive mode, key in the 4 non-comment lines of the abs( ) function as you see them above. Afterward, have abs( ) evaluate a positive and a negative number to show that the function is installed and ready to go. Within bc, at its (non-visual, beginning of line) prompt:

define abs(n){
if(n>=0) return(n)
return(-n)
}

abs(5)
abs(-12)
quit

Then let's put these 2 functions into a function "library" file. Create file "myfuincs.bc" with your editor and copy/paste into it both the above functions. Now put them in bc's hands on its command line:

bc  -q  -l  myfuncs.bc

Within bc:

abs(5)
abs(-12)
sign(10)
sign(0)
sign(-12)
quit

All good. Build your myfuncs.bc library by writing 3 new functions of your own into it. Follow the above syntax as your model for the bc language. The names and operations of your 3 new functions should be:

 min( ) - takes two numbers as parameters and returns the lesser
 max( ) - takes two numbers as parameters and returns the greater
 miles_to_kilometers( ) - takes a number and converts it from miles to kilometers (a kilometer is 5/8 of a mile)

After writing these in myfuncs.bc, invoke bc with it and test out your functions, making sure they work as intended:

bc  -q  -l  myfuncs.bc

min(3,11)
min(11,3)
min(3,3)
max(3,11)
max(11,3)
max(3,3)
miles_to_kilometers(100)
quit

 

Another way to put these functions into bc is with an interpreter script.

cp  myfuncs.bc  mybc.sh
sed  -i   '1i#!/usr/bin/bc -lq'   mybc.sh
head  mybc.sh
chmod  +x  mybc.sh
./mybc.sh
min(44,55)
abs(-75)
quit

You call the interpreter script, it calls the interpreter (bc), bc runs the rest of what's in the file (5 function definitions). So now you're in bc, with those functions loaded., and you tested that a couple of them indeed work.

You can run bc transparently from a script, never exposing the user to its command line. Key in or copy/paste this code into a file called myscript.sh and run it. Note that when bc is asked to execute a function, the 3 ways in which the function is being delivered/defined to bc.

#!/bin/bash

echo "scale=0;pow(3,4);scale=5;pow(2,0.5)" | bc -l funcs.bc
echo "farenheit_to_celcius(212)" | bc -l thermometer.bc
echo "max(22,33)" | bc -lq myfuncs.bc

# error, no triple( ) function ever given to bc
echo "triple(6)" | bc -lq

#give bc a triple( ) function via standard input, produced in shell by echo'ing
echo "define triple(n){ return(3*n) }; triple(6)" | bc -lq

#give bc a triple( ) function via standard input, produced in shell by cat'ing a (here) file
cat<<EOF | bc
define triple(n){
return(3*n)
}
triple(6)
EOF