{"id":4899,"date":"2021-07-12T22:43:00","date_gmt":"2021-07-13T01:43:00","guid":{"rendered":"https:\/\/bureau-it.com\/artigos\/how-to-use-bc-the-shell-calculator\/"},"modified":"2024-09-19T22:34:32","modified_gmt":"2024-09-20T01:34:32","slug":"how-to-use-bc-the-shell-calculator","status":"publish","type":"post","link":"https:\/\/bureau-it.com\/en\/artigos\/how-to-use-bc-the-shell-calculator\/","title":{"rendered":"How to use bc, the shell calculator"},"content":{"rendered":"\n

<\/span>Estimated reading time: <\/span>15<\/span> minutes<\/span><\/p>\n\n

Modes of use<\/h2>\n\n

First things first.\nTo get started with bc<\/code>, it’s important to know that there are two ways to use it: interactive or non-interactive.\nUsing the interactive mode is easy, just type in bc <\/code>and start the commands. <\/p>\n\n

$ bc\nbc 1.06\nCopyright 1991-1994, 1997, 1998, 2000 Free Software Foundation, Inc.\nThis is free software with ABSOLUTELY NO WARRANTY.\nFor details type `warranty'.\n1+1\n2<\/pre>\n\n

In non-interactive mode, you need to pass a string to the bc’s stdin somehow.\necho, printf, pipe, here strings… choose the most convenient one and go for it.\nLet’s look at some examples: <\/p>\n\n

\n
\n
\n
$ echo \"10*10\" | bc  #via pipe\n100<\/pre>\n\n\n\n
$ bc <<< \"10-3\"  #via here strings\n7<\/pre>\n<\/div>\n<\/div>\n<\/div><\/div>\n\n

Variables<\/h2>\n\n

bc<\/code> has 4 important variables that it uses internally:<\/p>\n\n

ibase   #base dos n\u00fameros de entrada (input) no c\u00e1lculo\nobase   #base do n\u00famero do resultado (de sa\u00edda, output) do c\u00e1lculo\nscale   #define a quantidade de d\u00edgitos ap\u00f3s a v\u00edrgula ap\u00f3s opera\u00e7\u00f5es de divis\u00e3o\nlast    #repete o \u00faltimo n\u00famero calculado <\/pre>\n\n

You can also define your own variables, but always in lower case<\/strong>. <\/p>\n\n

$ bc\nbc 1.06\nCopyright 1991-1994, 1997, 1998, 2000 Free Software Foundation, Inc.\nThis is free software with ABSOLUTELY NO WARRANTY.\nFor details type `warranty'.a = 1\nb = 2\nc = a + b\nc\n3<\/pre>\n\n

The bc does not tolerate upper cases in variables, but it does require upper cases for all hexadecimal entries!\nBe aware of this =) <\/p>\n\n

Hexadecimal, decimal, octal, binary and similar conversions…<\/h2>\n\n

This calculator becomes even more interesting when we need to change bases.\nFor example, to convert hexadecimal (base 16) to decimal (base 10), simply change the ibase (input) and obase (output) variables.\nBoth are 10 by default.\nSo let’s just change ibase, since the output will be decimal by default: <\/p>\n\n

$ echo \"ibase=16; FF\" | bc\n255<\/pre>\n\n

Or to convert from base 16 (hex) to base 2 (binary) with the arguments ibase<\/code> (input) and obase<\/code> (output) declared together:<\/p>\n\n

$ echo \"ibase=16; obase=2; FF\" | bc\n11111111<\/pre>\n\n

Operators<\/h2>\n\n

The basics:<\/p>\n\n

+ addition– subtraction* multiplication\/ division% remainder^ power<\/p>\n\n

Here’s bc in action with some commands and my comments alongside (yes, it accepts comments using # after each command).\nTo enter interactive mode, just call the command bc<\/code>. <\/p>\n\n

$ bc -q\n10*10 #c\u00e1lculo com base 10, default\n100\nibase=16 #altera\u00e7\u00e3o do input para base 16 (hex)\nFF\n255 #output de FF\nFF*2\n510 #output de FF*2\nobase=2 #troca a base do output para 2 (bin\u00e1rio)\nFF\n11111111 #resultado de FF\nFF*2\n111111110 #resultado de FF*2\nibase=2 #troca base do input para 2\nobase=A #troca base do output para 10 (escrito em hex). Aqui tem uma pegadinha, se colocar 10 o BC ir\u00e1 se perder.\nobase #chama a vari\u00e1vel obase\n10 #exibe o valor que consta na vari\u00e1vel obase, igual no python \ud83d\ude42 \n11111111\n255 #resultado de 11111111 em decimal\nlast #exibe o \u00faltimo resultado\n255\nscale=3 #define os d\u00edgitos ap\u00f3s v\u00edrgula\n23\/3\n7.666\nquit #sai do bc interativo<\/pre>\n\n

Other functions<\/h2>\n\n

Need more?\nLogarithm, sine, cosine, tangent etc?\nUse the bc math library with the –mathlib option <\/p>\n\n

$ bc --mathlib\ns(1)\n.84147098480789650665\nc(1)\n.54030230586813971740\na(1)\n.78539816339744830961<\/pre>\n\n

And the bc can even make programs!\nSee this example from the bc manual, the check book.\nSave the code below in any file, for example checkbook.bc<\/code><\/p>\n\n

scale=2\nprint \"\\nCheck book program!\\n\"\nprint \"  Remember, deposits are negative transactions.\\n\"\nprint \"  Exit by a 0 transaction.\\n\\n\"\nprint \"Initial balance? \"; bal = read()\nbal \/= 1\nprint \"\\n\"\nwhile (1) {\n   \"current balance = \"; bal\n   \"transaction? \"; trans = read()\n   if (trans == 0) break;\n   bal -= trans\n   bal \/= 1\n}\nquit<\/pre>\n\n

Now run it.<\/p>\n\n

$ bc -q checkbook.bc\n\n\nCheck book program!\n  Remember, deposits are negative transactions.\n\n  Exit by a 0 transaction.\n\nInitial balance? 2\n\ncurrent balance = 2.00\ntransaction? 1\ncurrent balance = 1.00\ntransaction? 1\ncurrent balance = 0\ntransaction? 1\ncurrent balance = -1.00\ntransaction? 0\n\nquit<\/pre>\n\n

There are many other functions in the bc, worth exploring if you want to delve into the subject.\nThe bc manual is very interesting, certainly worth a look. <\/p>\n\n

But before I end the article, take a look at this huge archive of bc functions! <\/p>\n\n

#!\/usr\/local\/bin\/bc -l\n\n### Funcs.BC - a large number of functions for use with GNU BC\n\n  ## Not to be regarded as suitable for any purpose\n  ## Not guaranteed to return correct answers\n\nscale=50;\ndefine pi() {\n  auto s;\n  if(scale==(s=scale(pi_)))return pi_\n  if(scale<s)return pi_\/1\n  scale+=5;pi_=a(1)*4;scale-=5\n  return pi_\/1\n}\ne = e(1);\ndefine phi(){return((1+sqrt(5))\/2)} ; phi = phi()\ndefine psi(){return((1-sqrt(5))\/2)} ; psi = psi()\n\n# Reset base to ten\nobase=ibase=A;\n\n## Integer and Rounding\n\n# Round to next integer nearest 0:  -1.99 -> 1, 0.99 -> 0\ndefine int(x)   { auto os;os=scale;scale=0;x\/=1;scale=os;return(x) } \n\n# Round down to integer below x\ndefine floor(x) {\n  auto os,xx;os=scale;scale=0\n  xx=x\/1;if(xx>x).=xx--\n  scale=os;return(xx)\n}\n\n# Round up to integer above x\ndefine ceil(x) {\n  auto os,xx;x=-x;os=scale;scale=0\n  xx=x\/1;if(xx>x).=xx--\n  scale=os;return(-xx)\n}\n\n# Fractional part of x:  12.345 -> 0.345\ndefine frac(x) {\n  auto os,xx;os=scale;scale=0\n  xx=x\/1;if(xx>x).=xx--\n  scale=os;return(x-xx)\n}\n\n# Absolute value of x\ndefine abs(x) { if(x<0)return(-x)else return(x) }\n\n# Sign of x\ndefine sgn(x) { if(x<0)return(-1)else if(x>0)return(1);return(0) }\n\n# Round x up to next multiple of y\ndefine round_up(  x,y) { return(y*ceil( x\/y )) }\n\n# Round x down to previous multiple of y\ndefine round_down(x,y) { return(y*floor(x\/y )) }\n\n# Round x to the nearest multiple of y\ndefine round(     x,y) {\n  auto os,oib;\n  os=scale;oib=ibase\n  .=scale++;ibase=A\n    y*=floor(x\/y+.5)\n  ibase=oib;scale=os\n  return y\n}\n\n# Find the remainder of x\/y\ndefine int_remainder(x,y) {\n  auto os;\n  os=scale;scale=0\n   x\/=1;y\/=1;x%=y\n  scale=os\n  return(x)\n}\ndefine remainder(x,y) {\n  os=scale;scale=0\n   if(x==x\/1&&y==y\/1){scale=os;return int_remainder(x,y)}\n  scale=os\n  return(x-round_down(x,y))\n}\n\n# Greatest common divisor of x and y\ndefine int_gcd(x,y) {\n  auto r,os;\n  os=scale;scale=0\n  x\/=1;y\/=1\n  while(y>0){r=x%y;x=y;y=r}\n  scale=os\n  return(x)\n}\ndefine gcd(x,y) {\n  auto r,os;\n  os=scale;scale=0\n   if(x==x\/1&&y==y\/1){scale=os;return int_gcd(x,y)}\n  scale=os\n  while(y>0){r=remainder(x,y);x=y;y=r}\n  return(x)\n}\n\n# Lowest common multiple of x and y\ndefine int_lcm(x,y) {\n  auto r,m,os;\n  os=scale;scale=0\n  x\/=1;y\/=1\n  m=x*y\n  while(y>0){r=x%y;x=y;y=r}\n  m\/=x\n  scale=os\n  return(m)\n}\ndefine lcm(x,y) { return (x*y\/gcd(x,y)) }\n\n# Remove largest possible power of 2 from x\ndefine oddpart(x){\n  auto os;\n  os=scale;scale=0;x\/=1\n  if(x==0){scale=os;return 1}\n  while(!x%2)x\/=2\n  scale=os;return x\n}\n\n# Largest power of 2 in x\ndefine evenpart(x) {\n  auto os;\n  os=scale;scale=0\n  x\/=oddpart(x\/1)\n  scale=os;return x\n}\n\n## Trig \/ Hyperbolic Trig\n\n# Sine\ndefine sin(x) { return s(x) } # alias for standard library\n# Cosine\ndefine c(x)   { return s(x+pi()\/2) } # as fast or faster than\ndefine cos(x) { return c(x)        } # . standard library\n# Tangent\ndefine tan(x)   { auto c;c=c(x);if(c==0)c=A^-scale;return(s(x)\/c) }\n\n# Secant\ndefine sec(x)   { auto c;c=c(x);if(c==0)c=A^-scale;return(   1\/c) }\n# Cosecant\ndefine cosec(x) { auto s;s=s(x);if(s==0)s=A^-scale;return(   1\/s) }\n# Cotangent\ndefine cotan(x) { auto s;s=s(x);if(s==0)s=A^-scale;return(c(x)\/s) }\n\n# Arcsine\ndefine arcsin(x) { if(x==-1||x==1)return(pi()\/2*x);return( a(x\/sqrt(1-x*x)) ) } \n# Arccosine\ndefine arccos(x) { if(x==0)return(0);return pi()\/2-arcsin(x) }\n\n# Arctangent (one argument)\ndefine arctan(x)  { return a(x) } # alias for standard library\n\n# Arctangent (two arguments)\ndefine arctan2(x,y) { \n  auto p;\n  if(x==0&&y==0)return(0)\n  p=(1-sgn(y))*pi()*(2*(x>=0)-1)\/2\n  if(x==0||y==0)return(p)\n  return(p+a(x\/y))\n}\n\n# Arcsecant\ndefine arcsec(x)      { return( a(x\/sqrt(x*x-1)) ) }\n# Arccosecant\ndefine arccosec(x)    { return( a(x\/sqrt(x*x-1))+pi()*(sgn(x)-1)\/2 ) }\n# Arccotangent (one argument)\ndefine arccotan(x)    { return( a(x)+pi()\/2 ) }\n# Arccotangent (two arguments)\ndefine arccotan2(x,y) { return( arctan(x,y)+pi()\/2 ) }\n\n# Hyperbolic Sine\ndefine sinh(x) { auto t;t=e(x);return((t-1\/t)\/2) }\n# Hyperbolic Cosine\ndefine cosh(x) { auto t;t=e(x);return((t+1\/t)\/2) }\n# Hyperbolic Tangent\ndefine tanh(x) { auto t;t=e(x+x)-1;return(t\/(t+2)) }\n\n# Hyperbolic Secant\ndefine sech(x)   { auto t;t=e(x);return(2\/(t+1\/t)) }\n# Hyperbolic Cosecant\ndefine cosech(x) { auto t;t=e(x);return(2\/(t-1\/t)) }\n# Hyperbolic Cotangent\ndefine coth(x)   { auto t;t=e(x+x)-1;return((t+2)\/t) }\n\n# Hyperbolic Arcsine\ndefine arcsinh(x) { return( l(x+sqrt(x*x+1)) ) }\n# Hyperbolic Arccosine\ndefine arccosh(x) { return( l(x+sqrt(x*x-1)) ) }\n# Hyperbolic Arctangent\ndefine arctanh(x) { return( l((1+x)\/(1-x))\/2 ) }\n\n# Hyperbolic Arcsecant\ndefine arcsech(x)   { return( l((sqrt(1-x*x)+1)\/x) ) }\n# Hyperbolic Arccosecant\ndefine arccosech(x) { return( l((sqrt(1+x*x)*sgn(x)+1)\/x) ) }\n# Hyperbolic Arccotangent\ndefine arccoth(x)   { return( l((x+1)\/(x-1))\/2 ) }\n\n# Length of the diagonal vector (0,0)-(x,y) [pythagoras]\ndefine pyth(x,y) { return(sqrt(x*x+y*y)) }\ndefine pyth3(x,y,z) { return(sqrt(x*x+y*y+z*z)) }\n\n# Gudermannian Function\ndefine gudermann(x)    { return 2*(a(e(x))-a(1)) }\n# Inverse Gudermannian Function\ndefine arcgudermann(x) {\n  return arctanh(s(x))\n}\n\n# Bessel function\ndefine besselj(n,x) { return j(n,x) } # alias for standard library\n\n## Exponential \/ Logs\n\n# Exponential e^x\ndefine exp(x) { return e(x) } # alias for standard library\n\n# Natural Logarithm (base e)\ndefine ln(x) {\n  auto os,len,ln;\n  if(x< 0){print \"ln error: logarithm of a negative number\\n\";return 0}\n  if(x==0)print \"ln error: logarithm of zero; negative infinity\\n\"\n  len=length(x)-scale(x)-1\n  if(len<A)return l(x);\n  os=scale;scale+=length(len)+1\n  ln=l(x\/A^len)+len*l(A)\n  scale=os\n  return ln\/1\n} # speed improvement on standard library\n\n# workhorse function for pow and log - new, less clever version\n# Helps determine whether a fractional power is legitimate for a negative number\n# . expects to be fed a positive value\n# . returns -odd for even\/odd; odd2 for odd1\/odd2;\n#           even for odd\/even;   -2 for irrational\n# . note that the return value is the denominator of the fraction if the\n#   fraction is rational, and the sign of the return value states whether\n#   the numerator is odd (positive) or even (negative)\n# . since even\/even is not possible, -2 is used to signify irrational\ndefine id_frac2_(y){\n  auto os,oib,es,eps,lim,max,p,max2,i,cf[],f[],n,d,t;\n  os=scale\n  if(cf_max){\n    # cf.bc is present!\n    .=cf_new(cf[],y);if(scale(cf[0]))return -2;\n    .=frac_from_cf(f[],cf[],1)\n    d=f[0];scale=0;if(f[1]%2==0)d=-d;scale=os\n   return d\n  }\n  oib=ibase;ibase=A\n  scale=0\n   es=3*os\/4\n  scale=os\n   eps=A^-es\n   y+=eps\/A\n  scale=es\n   y\/=1\n  scale=0\n  if(y<0)y=-y\n  d=y-(n=y\/1)\n  if(d<eps){t=2*(n%2)-1;scale=os;ibase=oib;return t}#integers are x\/1\n  t=y\/2;t=y-t-t\n  # Find numerator and denominator of fraction, if any\n  lim=A*A;max2=A^5*(max=A^int(os\/2));p=1\n  i=0;y=t\n  while(1) {\n    scale=es;y=1\/y;scale=0\n    y-=(t=cf[++i]=y\/1);p*=1+t\n    if(i>lim||(max<p&&p<max2)){cf[i=1]=-2;break}#escape if number seems irrational    \n    if((p>max2||3*length(t)>es+es)&&i>1){cf[i--]=0;break}#cheat: assume rational\n    if(y==0)break;#completely rational\n  }\n  n=1;d=cf[i]\n  if(i==0){print \"id_frac2_: something is wrong; y=\",y,\", d=\",d,\"\\n\"}\n  if(d!=-2&&i)while(--i){d=n+cf[i]*(t=d);n=t}\n  if(d<A^os){d*=2*(n%2)-1}else{d=-2}\n  scale=os;ibase=oib\n  return d;\n}\n\n# raise x to integer power y faster than bc's x^y\n# . it seems bc (at time of writing) uses\n# . an O(n) repeated multiplication algorithm\n# . for the ^ operator, which is inefficient given\n# . that there is a simple O(log n) alternative:\ndefine fastintpow__(x,y) {\n  auto r,hy;\n  if(y==0)return(1)\n  if(y==1)return(x)\n  r=fastintpow__(x,hy=y\/2)\n  r*=r;if(hy+hy<y)r*=x\n  return( r )\n}\ndefine fastintpow_(x,y) {\n  auto ix,os;\n  if(y<0)return fastintpow_(1\/x,-y)\n  if(y==0)return(1)\n  if(y==1)return(x)\n  if(x==1)return(1)\n  os=scale;scale=0\n  if(x==-1){y%=2;y+=y;scale=os;return 1-y}\n  # bc is still faster for integers\n  if(x==(ix=x\/1)){scale=os;return ix^y}\n  # ...and small no. of d.p.s, but not for values <= 2\n  if(scale(x)<3&&x>2){scale=os;return x^y}\n  scale=os;x\/=1;scale=0\n  x=fastintpow__(x,y);\n  scale=os;return x;\n}\n\n# Raise x to a fractional power faster than e^(y*l(x))\ndefine fastfracpow_(x,y) {\n  auto f,yy,inv;\n  inv=0;if(y<0){y=-y;inv=1}\n  y-=int(y)\n  if(y==0)return 1;\n  if((yy=y*2^C)!=int(yy)){x=l(x);if(inv)x=-x;return e(y\/1*x)}\n  # faster using square roots for rational binary fractions\n  # where denominator <= 8192\n  x=sqrt(x)\n  for(f=1;y&&x!=1;x=sqrt(x))if(y+=y>=1){.=y--;f*=x}\n  if(inv)f=1\/f;\n  return f;\n}\n\n# Find the yth root of x where y is integer\ndefine fastintroot_(x,y) {\n  auto os,d,r,ys,eps;\n  os=scale;scale=0;y\/=1;scale=os\n  if(y<0){x=1\/x;y=-y}\n  if(y==1){return x}\n  if(y>=x-1){return fastfracpow_(x,1\/y)}\n  if(y*int((d=2^F)\/y)==d){\n    r=1;while(r+=r<=y)x=sqrt(x)\n    return x\n  }\n  scale=length(y)-scale(y);if(scale<5)scale=5;r=e(ln(x)\/y)\n  scale=os+5;if(scale<5)scale=5\n  d=1;eps=A^(3-scale)\n  ys=y-1\n  while(d>eps){\n    d=r;r=(ys*r+x\/fastintpow_(r,ys))\/y\n    d-=r;if(d<0)d=-d\n  }\n  scale=os\n  return r\/1\n}\n\n# Raise x to the y-th power\ndefine pow(x,y) {\n auto os,p,ix,iy,fy,dn,s;\n if(y==0) return 1\n if(x==0) return 0\n if(0<x&&x<1){x=1\/x;y=-y}\n os=scale;scale=0\n  ix=x\/1;iy=y\/1;fy=y-iy;dn=0\n scale=os;#scale=length(x\/1)\n if(y!=iy&&x<0){\n   dn=id_frac2_(y)# -ve implies even numerator\n   scale=0;if(dn%2){# odd denominator\n     scale=os\n     if(dn<0)return  pow(-x,y) # even\/odd\n     \/*else*\/return -pow(-x,y) #  odd\/odd\n   }\n   print \"pow error: \"\n   if(dn>0) print \"even root\"\n   if(dn<0) print \"irrational power\"\n   print \" of a negative number\\n\"\n   scale=os;return 0\n }\n if(y==iy) {\n   if(x==ix){p=fastintpow_(ix,iy);if(iy>0){scale=0;p\/=1};scale=os;return p\/1}\n   scale+=scale;p=fastintpow_(x,iy);scale=os;return p\/1\n }\n if((dn=id_frac2_(y))!=-2){ #accurate rational roots (sometimes slower)\n   if(dn<0)dn=-dn\n   s=1;if(y<0){y=-y;s=-1}\n   p=y*dn+1\/2;scale=0;p\/=1;scale=os\n   if(p<A^3)x=fastintpow_(x,p)\n   x=fastintroot_(x,dn)\n   if(p>=A^3)x=fastintpow_(x,p)\n   if(s<0)x=1\/x\n   return x\n }\n p=fastintpow_(ix,iy)*fastfracpow_(x,fy);\n scale=os+os\n if(ix)p*=fastintpow_(x\/ix,iy)\n scale=os\n return p\/1\n #The above is usually faster and more accurate than\n # return( e(y*l(x)) );\n}\n\n# y-th root of x [ x^(1\/y) ]\ndefine root(x,y) {\n  return pow(x,1\/y)\n}\n\n# Specific cube root function\n# = stripped down version of fastintroot_(x,3)\ndefine cbrt(x) {\n  auto os,d,r,eps;\n  if(x<0)return -cbrt(-x)\n  if(x==0)return 0\n  os=scale;scale=0;eps=A^(scale\/3)\n  if(x<eps){scale=os;return 1\/cbrt(1\/x)}\n  scale=5;r=e(ln(x)\/3)\n  scale=os+5;if(scale<5)scale=5\n  d=1;eps=A^(3-scale)\n  while(d>eps){\n    d=r;r=(r+r+x\/(r*r))\/3\n    d-=r;if(d<0)d=-d\n  }\n  scale=os\n  return r\/1\n}\n\n# Logarithm of x in given base:  log(2, 32) = 5 because 2^5 = 32\n#  tries to return a real answer where possible when given negative numbers\n#  e.g.     log(-2,  64) = 6 because (-2)^6 =   64\n#  likewise log(-2,-128) = 7 because (-2)^7 = -128\ndefine log(base,x) {\n  auto os,i,l,sx,dn,dnm2;\n  if(base==x)return 1;\n  if(x==0){print \"log error: logarithm of zero; negative infinity\\n\";     return  l(0)}\n  if(x==1)return 0;\n  if(base==0){print \"log error: zero-based logarithm\\n\";                  return    0 }\n  if(base==1){print \"log error: one-based logarithm; positive infinity\\n\";return -l(0)}\n  scale+=6\n  if((-1<base&&base<0)||(0<base&&base<1)){x=-log(1\/base,x);scale-=6;return x\/1}\n  if((-1<x   &&   x<0)||(0<x   &&   x<1)){x=-log(base,1\/x);scale-=6;return x\/1}\n  if(base<0){\n    sx=1;if(x<0){x=-x;sx=-1}\n    l=log(-base,x)\n    dn=id_frac2_(l)\n    os=scale;scale=0;dnm2=dn%2;scale=os\n    if(dnm2&&dn*sx<0){scale-=6;return l\/1}\n    print \"log error: -ve base: \"\n    if(dnm2)print \"wrong sign for \"\n    print \"implied \"\n    if(dnm2)print \"odd root\/integer power\\n\"\n    if(!dnm2){\n      if(dn!=-2)print \"even root\\n\"\n      if(dn==-2)print \"irrational power\\n\"\n    }\n    scale-=6;return 0;\n  }\n  if(x<0){\n    print \"log error: +ve base: logarithm of a negative number\\n\"\n    scale-=6;return 0;\n  }\n  x=ln(x)\/ln(base);scale-=6;return x\/1\n}\n\n# Integer-only logarithm of x in given base\n# (compare digits function in digits.bc)\ndefine int_log(base,x) { \n auto os,p,c;\n if(0<x&&x<1) {return -int_log(base,1\/x)}\n os=scale;scale=0;base\/=1;x\/=1\n  if(base<2)base=ibase;\n  if(x==0)    {scale=os;return  1-base*A^os}\n  if(x<base)  {scale=os;return  0    }\n  c=length(x) # cheat and use what bc knows about decimal length\n  if(base==A){scale=os;return c-1}\n  if(base<A){if(x>A){c*=int_log(base,A);c-=2*(base<4)}else{c=0}}else{c\/=length(base)+1}\n  p=base^c;while(p<=x){.=c++;p*=base}\n  scale=os;return(c-1)\n}\n\n# Lambert's W function 0 branch; Numerically solves w*e(w) = x for w\n# * is slow to converge near -1\/e at high scales\ndefine lambertw0(x) {\n  auto oib, a, b, w, ow, lx, ew, e1, eps;\n  if(x==0) return 0;\n  oib=ibase;ibase=A\n  ew = -e(-1)\n  if (x<ew) {\n    print \"lambertw0: expected argument in range [-1\/e,oo)\\n\"\n    ibase=oib\n    return -1\n  }\n  if (x==ew) {ibase=oib;return -1}\n  # First approximation from :\n  #   http:\/\/www.desy.de\/~t00fri\/qcdins\/texhtml\/lambertw\/\n  #   (A. Ringwald and F. Schrempp)\n  # via Wikipedia\n  if(x < 0){\n    w = x\/ew\n  } else if(x < 500){\n    lx=l(x+1);w=0.665*(1+0.0195*lx)*lx+0.04\n  } else if((lx=length(x)-scale(x))>5000) {\n    lx*=l(A);w=lx-(1-1\/lx)*l(lx)\n  } else {\n    lx=l(x);w=l(x-4)-(1-1\/lx)*l(lx)\n  } \n  # Iteration adapted from code found on Wikipedia\n  #   apparently by an anonymous user at 147.142.207.26\n  #   and later another at 87.68.32.52\n  ow = 0\n  eps = A^-scale\n  scale += 5\n  e1 = e(1)\n  while(abs(ow-w)>eps&&w>-1){\n    ow = w\n    if(x>0){ew=pow(e1,w)}else{ew=e(w)}\n    a = w*ew\n    b = a+ew\n    a -= x;\n    if(a==0)break\n    b = b\/a - 1 + 1\/(w+1)\n    w -= 1\/b\n    if(x<-0.367)w-=eps\n  }\n  scale -= 5\n  ibase=oib\n  return w\/1\n}\n\n# Lambert's W function -1 branch; Numerically solves w*e(w) = x for w\n# * is slow to converge near -1\/e at high scales\ndefine lambertw_1(x) {\n  auto oib,os,oow,ow,w,ew,eps,d,iters;\n  oib=ibase;ibase=A\n  ew = -e(-1)\n  if(ew>x||x>=0) {\n    print \"lambertw_1: expected argument in [-1\/e,0)\\n\"\n    ibase=oib\n    if(x==0)return 1-A^scale\n    if(x>0)return 0\n    return -1\n  }\n  if(x==ew) return -1;\n  os=scale\n  eps=A^-os\n  scale+=3\n  oow=ow=0\n  w=x\n  w=l(-w)\n  w-=l(-w)\n  w+=sqrt(eps)\n  iters=0\n  while(abs(ow-w)>eps){\n    oow=ow;ow=w\n    if(w==-1)break\n    w=(x*e(-w)+w*w)\/(w+1)\n    if(iters++==A+A||oow==w){iters=0;w-=A^-scale;scale+=2}\n  }\n  scale=os;ibase=oib\n  return w\/1\n}\n\n# LambertW wrapper; takes most useful branch based on x\n# to pick a branch manually, use lambertw_1 or lambertw0 directly\ndefine w(x) {\n  if(x<0)return lambertw_1(x)\n  return lambertw0(x)\n}\n\n# Faster calculation of lambertw0(exp(x))\n# . avoids large intermediate value and associated slowness\n# . numerically solves x = y+ln(y) for y\ndefine lambertw0_exp(x) {\n  auto oy,y,eps;\n  # Actual calculation is faster for x < 160 or thereabouts\n  if(x<C*D)return lambertw0(e(x));\n  oy=0;y=l(x);y=x-y+y\/x;eps=A^-scale\n  while(abs(oy-y)>eps)y=x-l(oy=y)\n  return y\n}\n\n# Shorthand alias for the above\ndefine w_e(x){ return lambertw0_exp(x) }\n\n# Numerically solve pow(y,y) = x for y\ndefine powroot(x) {\n  auto r;\n  if(x==0) {\n    print \"powroot error: attempt to solve for zero\\n\"\n    return 0\n  }\n  if(x==1||x==-1) {return x}\n  if(x<=r=e(-e(-1))){\n    print \"powroot error: unimplemented for values\\n  <0\";r\n    return 0\n  }\n  r = ln(x)\n  r \/= w(r)\n  return r\n}\n\n## Triangular numbers\n\n# xth triangular number\ndefine tri(x) {\n  auto xx\n  x=x*(x+1)\/2;xx=int(x)\n  if(x==xx)return(xx)\n  return(x)\n}\n\n# 'triangular root' of x\ndefine trirt(x) {\n  auto xx\n  x=(sqrt(1+8*x)-1)\/2;xx=int(x)\n  if(x==xx)x=xx\n  return(x)\n}\n\n# Workhorse for following 2 functions\ndefine tri_step_(t,s) {\n  auto tt\n  t=t+(1+s*sqrt(1+8*t))\/2;tt=int(t)\n  if(tt==t)return(tt)\n  return(t)\n}\n\n# Turn tri(x) into tri(x+1) without knowing x\ndefine tri_succ(t) {\n  return(tri_step_(t,0+1))\n}\n\n# Turn tri(x) into tri(x-1) without knowing x\ndefine tri_pred(t) {\n  return(tri_step_(t,0-1))\n}\n\n## Polygonal Numbers\n\n# the xth s-gonal number:\n#   e.g. poly(3, 4) = tri(4) = 1+2+3+4 = 10; poly(4, x) = x*x, etc\ndefine poly(s, x) {\n  auto xx\n  x*=(s\/2-1)*(x-1)+1;xx=int(x);if(x==xx)x=xx\n  return x\n}\n\n# inverse of the above = polygonal root:\n#   e.g. inverse_poly(3,x)=trirt(x); inverse_poly(4,x)=sqrt(x), etc\ndefine inverse_poly(s, r) {\n  auto t,xx\n  t=(s-=2)-2\n  r=(sqrt(8*s*r+t*t)+t)\/s\/2;xx=int(r);if(r==xx)r=xx\n  return r\n}\n\n# converse of poly(); solves poly(s,x)=r for s\n#   i.e. if the xth polygonal number is r, how many sides has the polygon?\n#   e.g. if the 5th polygonal number is 15, converse_poly(5,15) = 3\n#     so the polygon must have 3 sides! (15 is the 5th triangular number)\ndefine converse_poly(x,r) {\n  auto xx\n  x=2*((r\/x-1)\/(x-1)+1);xx=int(x);if(x==xx)x=xx\n  return x\n}\n\n## Tetrahedral numbers\n\n# nth tetrahedral number\ndefine tet(n) { return n*(n+1)*(n+2)\/6 }\n\n# tetrahedral root = inverse of the above\ndefine tetrt(t) {\n  auto k,c3,w;\n  if(t==0)return 0\n  if(t<0)return -2-tetrt(-t)\n  k=3^5*t*t-1\n  if(k<0){print \"tetrt: unimplemented for 0<|t|<sqrt(3^-5)\\n\"; return 0}\n  c3=cbrt(3)\n  k=cbrt(sqrt(3*k)+3^3*t)\n  return k\/c3^2+1\/(c3*k)-1\n}\n\n## Arithmetic-Geometric mean\n\ndefine arigeomean(a,b) {\n  auto c,s;\n  if(a==b)return a;\n  s=1;if(a<0&&b<0){s=-1;a=-a;b=-b}\n  if(a<0||b<0){print \"arigeomean: mismatched signs\\n\";return 0}\n  while(a!=b){c=(a+b)\/2;a=sqrt(a*b);b=c}\n  return s*a\n}\n\n# solve n = arigeomean(x,y)\ndefine inv_arigeomean(n, y){\n  auto ns,ox,x,b,c,d,i,s,eps;\n  if(n==y)return n;\n  s=1;if(n<0&&y<0){s=-1;n=-n;y=-y}\n  if(n<0||y<0){print \"inv_arigeomean: mismatched signs\\n\";return 0}  \n  if(n<y){x=y;y=n;n=x}\n  n\/=y\n  scale+=2;eps=A^-scale;scale+=4\n  ns=scale\n  x=n*(1+ln(n));ox=-1\n  for(i=0;i<A;i++){\n    # try to force quadratic convergence\n    if(abs(x-ox)<eps){i=-1;break}\n    ox=x;scale+=scale\n    b=x+x\/n*(n-arigeomean(1,x));\n    c=b+b\/n*(n-arigeomean(1,b));\n    d=b+b-c-x\n    if(d){x=(b*b-c*x)\/d}else{x=b;i=-1;break}\n    scale=ns\n  }\n  if(i!=-1){\n    # give up and converge linearly\n    x=(x+ox)\/2\n    while(abs(x-ox)>eps){ox=x;x+=x\/n*(n-arigeomean(1,x))}\n  }\n  x+=5*eps\n  scale-=6;return x*y\/s\n}<\/pre>\n\n

I’ve kept the original script, but I recommend that you replace the first line with<\/p>\n\n

#!\/usr\/bin\/env bc -l<\/pre>\n\n

This will prevent the shell from getting lost and not finding the bc on the right path!<\/p>\n\n

To use it, save it with any name, such as funcs.bc<\/code>, make it executable with chmod +x<\/code> and run it as .\/funcs.bc<\/code>.\nChoose one of the functions in the script and fill it in with the numbers, like the cube root of 27 in the example below.\nType quit<\/code> to exit the interactive mode of bc<\/code>. <\/p>\n\n

.\/funcs.bc\nbc 1.06\nCopyright 1991-1994, 1997, 1998, 2000 Free Software Foundation, Inc.\nThis is free software with ABSOLUTELY NO WARRANTY.\nFor details type `warranty'.\nroot(27,3)\n3.00000000000000000000000000000000000000000000000000\nquit<\/pre>\n\n

Configure .bcrc<\/h2>\n\n

To load your favorite functions automatically, create a file at ~\/.bcrc<\/code> containing all of them.\nA good suggestion for starting your .bcrc <\/code> is at https:\/\/github.com\/idealvin\/bc\/blob\/master\/bcrc<\/a> <\/p>\n\n

pi=4*a(1);\ne=e(1);\n\ndefine sin(x) {\n    if (x == pi\/2) {\n        return 1;\n    }\n\n    return s(x);\n}\n\ndefine cos(x) {\n    if (x == pi\/2) {\n        return 0;\n    }\n\n    return c(x);\n}\n\ndefine tan(x) {\n    if (x == pi\/4) {\n        return 1;\n    }\n\n    if (x == -pi\/4) {\n        return -1;\n    }\n\n    return s(x)\/c(x);\n}\n\ndefine cot(x) {\n    if (x == pi\/4) {\n        return 1;\n    }\n\n    if (x == -pi\/4) {\n        return -1;\n    }\n\n    return c(x)\/s(x);\n}\n\ndefine sec(x) {\n    return 1\/cos(x);\n}\n\ndefine csc(x) {\n    return 1\/sin(x);\n}\n\ndefine asin(x) {\n    if (x == 1) {\n        return pi\/2;\n    }\n\n    if (x == -1) {\n        return -pi\/2;\n    }\n\n    return a(x\/sqrt(1-x^2));\n}\n\ndefine arcsin(x) {\n    return asin(x);\n}\n\ndefine acos(x) {\n    if (x == 0) {\n        return pi\/2;\n    }\n\n    if (x == 1) {\n        return 0;\n    }\n\n    if (x == -1) {\n        return pi\/1;\n    }\n\n    if (x > 0) {\n        return a(sqrt(1-x^2)\/x);\n    }\n\n    return pi\/1 - acos(-x);\n}\n\ndefine arccos(x) {\n    return acos(x);\n}\n\ndefine atan(x) {\n    if (x == 1) {\n        return pi\/4;\n    }\n\n    if (x == -1) {\n        return -pi\/4;\n    }\n\n    return a(x);\n}\n\ndefine arctan(x) {\n    return a(x);\n}\n\ndefine acot(x) {\n    return pi\/2-atan(x);\n}\n\ndefine arccot(x) {\n    return acot(x);\n}\n\ndefine asec(x) {\n    if (x >= 1) {\n        return a(sqrt(x^2-1));\n    }\n\n    return pi\/1 - a(sqrt(x^2-1));\n}\n\ndefine arcsec(x) {\n    return asec(x);\n}\n\ndefine acsc(x) {\n    if (x == 1) {\n        return pi\/2;\n    }\n\n    if (x == -1) {\n        return -pi\/2;\n    }\n\n    if (x > 1) {\n        return a(1\/sqrt(x^2-1));\n    }\n\n    return -a(1\/sqrt(x^2-1));\n}\n\ndefine arccsc(x) {\n    return acsc(x);\n}\n\ndefine ln(x) {\n    return l(x);\n}\n\ndefine log(a, b) {\n    return l(b)\/l(a);\n}\n\ndefine lg(x) {\n    return log(10, x);\n}\n\ndefine log10(x) {\n    return log(10, x);\n}\n\ndefine log2(x) {\n    return log(2, x);\n}\n\ndefine pow(a, b) {\n    if (scale(b) == 0) {\n        return a ^ b;\n    }\n    return e(b*l(a));\n}\n\ndefine exp(x) {\n    return e(x);\n}\n\ndefine cbrt(x) {\n    return pow(x, 1\/3);\n}\n\ndefine abs(x) {\n    if (x < 0) {\n        return -x;\n    }\n    return x;\n}\n\ndefine bessel(n, x) {\n    return j(n,x);\n}\n\ndefine a(m, n) {\n    if (n < 0) {\n        return 0;\n    }\n\n    v = 1;\n    for (i = 0; i < n; i++) {\n        v *= (m - i);\n    }\n    return v;\n}\n\ndefine fac(n) {\n    return a(n, n);\n}\n\ndefine c(m, n) {\n    auto v\n\n    if (n < 0) {\n        return 0;\n    }\n\n    s = scale;\n    scale = 0;\n    v = a(m, n) \/ a(n, n);\n    scale = s;\n    return v;\n}\n\ndefine rad(deg) {\n    return deg\/180*pi;\n}\n\ndefine deg(rad) {\n    return rad\/pi*180;\n}<\/pre>\n\n

Then enter the path of .bcrc<\/code> in your ~\/.bashrc<\/code>.\nUse the variable BC_ENV_ARGS<\/code> which is loaded by bc<\/code> every time it starts.\nI also suggest the option -l<\/code>, which loads the standard math library from bc<\/code>. <\/p>\n\n

export BC_ENV_ARGS=\"-l $HOME\/.bcrc\"<\/pre>\n\n

And that’s all for now.\nThis and many other scripts with incredible functions can be found on the phodd.net website.\nI recommend visiting the following links: <\/p>\n\n