Come utilizzare bc, il calcolatore di conchiglie

bc = calcolatrice da banco. Se non conosci ancora la calcolatrice della tua shell, è il momento di imparare a usarla, anche se il suo utilizzo è molto elementare. L'uso più banale delle sue funzioni dovrebbe già soddisfare la maggior parte delle tue esigenze. Ma non lasciarti ingannare: si tratta di un software davvero potente che dovrebbe essere assolutamente presente nel tuo radar.

Tempo di lettura stimato: 15 minuti

Modalità di utilizzo

Prima di tutto. bc Per iniziare è importante sapere che ci sono due modi per utilizzarlo: in modalità interattiva o non interattiva. bc Utilizzare la modalità interattiva è facile, basta digitare e avviare i comandi.

$ bc
bc 1.06
Copyright 1991-1994, 1997, 1998, 2000 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
1+1
2

In modalità non interattiva, devi passare una stringa allo stdin del bc in qualche modo. echo, printf, pipe, qui stringhe… scegli il metodo più comodo e procedi. Vediamo alcuni esempi:

$ echo "10*10" | bc  #via pipe
100
$ bc <<< "10-3"  #via here strings
7

Variabili

bc ha 4 importanti variabili che utilizza internamente:

ibase   #base dos números de entrada (input) no cálculo
obase   #base do número do resultado (de saída, output) do cálculo
scale   #define a quantidade de dígitos após a vírgula após operações de divisão
last    #repete o último número calculado 

Puoi anche definire le tue variabili, ma sempre in minuscolo.

$ bc
bc 1.06
Copyright 1991-1994, 1997, 1998, 2000 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.a = 1
b = 2
c = a + b
c
3

Il bc non tollera i bins alti nelle variabili, ma richiede bins alti per tutte le voci esadecimali! Tieni presente questo aspetto =)

Conversioni esadecimali, decimali, ottali, binarie e simili…

Questa calcolatrice diventa ancora più interessante quando dobbiamo cambiare le basi. Ad esempio, per convertire l’esadecimale (base 16) in decimale (base 10), basta cambiare le variabili ibase (ingresso) e obase (uscita). Entrambe sono in base 10 per impostazione predefinita. Quindi cambiamo solo ibase, dato che l’output sarà decimale per impostazione predefinita:

$ echo "ibase=16; FF" | bc
255

ibase obase Oppure per convertire dalla base 16 (esadecimale) alla base 2 (binaria) con gli argomenti (input) e (output) dichiarati insieme:

$ echo "ibase=16; obase=2; FF" | bc
11111111

Operatori

Le basi:






+ addizione – sottrazione * moltiplicazione / divisione % resto ^ potenza

Ecco bc in azione con alcuni comandi e i miei commenti a fianco (sì, accetta i commenti usando # dopo ogni comando). bcPer entrare in modalità interattiva, basta richiamare il comando .

$ bc -q
10*10 #cálculo com base 10, default
100
ibase=16 #alteração do input para base 16 (hex)
FF
255 #output de FF
FF*2
510 #output de FF*2
obase=2 #troca a base do output para 2 (binário)
FF
11111111 #resultado de FF
FF*2
111111110 #resultado de FF*2
ibase=2 #troca base do input para 2
obase=A #troca base do output para 10 (escrito em hex). Aqui tem uma pegadinha, se colocar 10 o BC irá se perder.
obase #chama a variável obase
10 #exibe o valor que consta na variável obase, igual no python 🙂 
11111111
255 #resultado de 11111111 em decimal
last #exibe o último resultado
255
scale=3 #define os dígitos após vírgula
23/3
7.666
quit #sai do bc interativo

Altre funzioni

Hai bisogno di altro? Logaritmo, seno, coseno, tangente e così via? Usa la libreria matematica di bc con l’opzione –mathlib

$ bc --mathlib
s(1)
.84147098480789650665
c(1)
.54030230586813971740
a(1)
.78539816339744830961

E il bc può anche creare programmi! Guarda questo esempio tratto dal manuale del bc, il libro degli assegni. Salva il codice qui sotto in un file qualsiasi, ad esempio checkbook.bc

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

Ora eseguilo.

$ bc -q checkbook.bc


Check book program!
  Remember, deposits are negative transactions.

  Exit by a 0 transaction.

Initial balance? 2

current balance = 2.00
transaction? 1
current balance = 1.00
transaction? 1
current balance = 0
transaction? 1
current balance = -1.00
transaction? 0

quit

Ci sono molte altre funzioni nel bc, che vale la pena esplorare se vuoi approfondire l’argomento. Il manuale del bc è molto interessante, vale sicuramente la pena darci un’occhiata.

Ma prima di concludere l’articolo, dai un’occhiata a questo enorme archivio di funzioni bc!

#!/usr/local/bin/bc -l

### Funcs.BC - a large number of functions for use with GNU BC

  ## Not to be regarded as suitable for any purpose
  ## Not guaranteed to return correct answers

scale=50;
define pi() {
  auto s;
  if(scale==(s=scale(pi_)))return pi_
  if(scale<s)return pi_/1
  scale+=5;pi_=a(1)*4;scale-=5
  return pi_/1
}
e = e(1);
define phi(){return((1+sqrt(5))/2)} ; phi = phi()
define psi(){return((1-sqrt(5))/2)} ; psi = psi()

# Reset base to ten
obase=ibase=A;

## Integer and Rounding

# Round to next integer nearest 0:  -1.99 -> 1, 0.99 -> 0
define int(x)   { auto os;os=scale;scale=0;x/=1;scale=os;return(x) } 

# Round down to integer below x
define floor(x) {
  auto os,xx;os=scale;scale=0
  xx=x/1;if(xx>x).=xx--
  scale=os;return(xx)
}

# Round up to integer above x
define ceil(x) {
  auto os,xx;x=-x;os=scale;scale=0
  xx=x/1;if(xx>x).=xx--
  scale=os;return(-xx)
}

# Fractional part of x:  12.345 -> 0.345
define frac(x) {
  auto os,xx;os=scale;scale=0
  xx=x/1;if(xx>x).=xx--
  scale=os;return(x-xx)
}

# Absolute value of x
define abs(x) { if(x<0)return(-x)else return(x) }

# Sign of x
define sgn(x) { if(x<0)return(-1)else if(x>0)return(1);return(0) }

# Round x up to next multiple of y
define round_up(  x,y) { return(y*ceil( x/y )) }

# Round x down to previous multiple of y
define round_down(x,y) { return(y*floor(x/y )) }

# Round x to the nearest multiple of y
define round(     x,y) {
  auto os,oib;
  os=scale;oib=ibase
  .=scale++;ibase=A
    y*=floor(x/y+.5)
  ibase=oib;scale=os
  return y
}

# Find the remainder of x/y
define int_remainder(x,y) {
  auto os;
  os=scale;scale=0
   x/=1;y/=1;x%=y
  scale=os
  return(x)
}
define remainder(x,y) {
  os=scale;scale=0
   if(x==x/1&&y==y/1){scale=os;return int_remainder(x,y)}
  scale=os
  return(x-round_down(x,y))
}

# Greatest common divisor of x and y
define int_gcd(x,y) {
  auto r,os;
  os=scale;scale=0
  x/=1;y/=1
  while(y>0){r=x%y;x=y;y=r}
  scale=os
  return(x)
}
define gcd(x,y) {
  auto r,os;
  os=scale;scale=0
   if(x==x/1&&y==y/1){scale=os;return int_gcd(x,y)}
  scale=os
  while(y>0){r=remainder(x,y);x=y;y=r}
  return(x)
}

# Lowest common multiple of x and y
define int_lcm(x,y) {
  auto r,m,os;
  os=scale;scale=0
  x/=1;y/=1
  m=x*y
  while(y>0){r=x%y;x=y;y=r}
  m/=x
  scale=os
  return(m)
}
define lcm(x,y) { return (x*y/gcd(x,y)) }

# Remove largest possible power of 2 from x
define oddpart(x){
  auto os;
  os=scale;scale=0;x/=1
  if(x==0){scale=os;return 1}
  while(!x%2)x/=2
  scale=os;return x
}

# Largest power of 2 in x
define evenpart(x) {
  auto os;
  os=scale;scale=0
  x/=oddpart(x/1)
  scale=os;return x
}

## Trig / Hyperbolic Trig

# Sine
define sin(x) { return s(x) } # alias for standard library
# Cosine
define c(x)   { return s(x+pi()/2) } # as fast or faster than
define cos(x) { return c(x)        } # . standard library
# Tangent
define tan(x)   { auto c;c=c(x);if(c==0)c=A^-scale;return(s(x)/c) }

# Secant
define sec(x)   { auto c;c=c(x);if(c==0)c=A^-scale;return(   1/c) }
# Cosecant
define cosec(x) { auto s;s=s(x);if(s==0)s=A^-scale;return(   1/s) }
# Cotangent
define cotan(x) { auto s;s=s(x);if(s==0)s=A^-scale;return(c(x)/s) }

# Arcsine
define arcsin(x) { if(x==-1||x==1)return(pi()/2*x);return( a(x/sqrt(1-x*x)) ) } 
# Arccosine
define arccos(x) { if(x==0)return(0);return pi()/2-arcsin(x) }

# Arctangent (one argument)
define arctan(x)  { return a(x) } # alias for standard library

# Arctangent (two arguments)
define arctan2(x,y) { 
  auto p;
  if(x==0&&y==0)return(0)
  p=(1-sgn(y))*pi()*(2*(x>=0)-1)/2
  if(x==0||y==0)return(p)
  return(p+a(x/y))
}

# Arcsecant
define arcsec(x)      { return( a(x/sqrt(x*x-1)) ) }
# Arccosecant
define arccosec(x)    { return( a(x/sqrt(x*x-1))+pi()*(sgn(x)-1)/2 ) }
# Arccotangent (one argument)
define arccotan(x)    { return( a(x)+pi()/2 ) }
# Arccotangent (two arguments)
define arccotan2(x,y) { return( arctan(x,y)+pi()/2 ) }

# Hyperbolic Sine
define sinh(x) { auto t;t=e(x);return((t-1/t)/2) }
# Hyperbolic Cosine
define cosh(x) { auto t;t=e(x);return((t+1/t)/2) }
# Hyperbolic Tangent
define tanh(x) { auto t;t=e(x+x)-1;return(t/(t+2)) }

# Hyperbolic Secant
define sech(x)   { auto t;t=e(x);return(2/(t+1/t)) }
# Hyperbolic Cosecant
define cosech(x) { auto t;t=e(x);return(2/(t-1/t)) }
# Hyperbolic Cotangent
define coth(x)   { auto t;t=e(x+x)-1;return((t+2)/t) }

# Hyperbolic Arcsine
define arcsinh(x) { return( l(x+sqrt(x*x+1)) ) }
# Hyperbolic Arccosine
define arccosh(x) { return( l(x+sqrt(x*x-1)) ) }
# Hyperbolic Arctangent
define arctanh(x) { return( l((1+x)/(1-x))/2 ) }

# Hyperbolic Arcsecant
define arcsech(x)   { return( l((sqrt(1-x*x)+1)/x) ) }
# Hyperbolic Arccosecant
define arccosech(x) { return( l((sqrt(1+x*x)*sgn(x)+1)/x) ) }
# Hyperbolic Arccotangent
define arccoth(x)   { return( l((x+1)/(x-1))/2 ) }

# Length of the diagonal vector (0,0)-(x,y) [pythagoras]
define pyth(x,y) { return(sqrt(x*x+y*y)) }
define pyth3(x,y,z) { return(sqrt(x*x+y*y+z*z)) }

# Gudermannian Function
define gudermann(x)    { return 2*(a(e(x))-a(1)) }
# Inverse Gudermannian Function
define arcgudermann(x) {
  return arctanh(s(x))
}

# Bessel function
define besselj(n,x) { return j(n,x) } # alias for standard library

## Exponential / Logs

# Exponential e^x
define exp(x) { return e(x) } # alias for standard library

# Natural Logarithm (base e)
define ln(x) {
  auto os,len,ln;
  if(x< 0){print "ln error: logarithm of a negative number\n";return 0}
  if(x==0)print "ln error: logarithm of zero; negative infinity\n"
  len=length(x)-scale(x)-1
  if(len<A)return l(x);
  os=scale;scale+=length(len)+1
  ln=l(x/A^len)+len*l(A)
  scale=os
  return ln/1
} # speed improvement on standard library

# workhorse function for pow and log - new, less clever version
# Helps determine whether a fractional power is legitimate for a negative number
# . expects to be fed a positive value
# . returns -odd for even/odd; odd2 for odd1/odd2;
#           even for odd/even;   -2 for irrational
# . note that the return value is the denominator of the fraction if the
#   fraction is rational, and the sign of the return value states whether
#   the numerator is odd (positive) or even (negative)
# . since even/even is not possible, -2 is used to signify irrational
define id_frac2_(y){
  auto os,oib,es,eps,lim,max,p,max2,i,cf[],f[],n,d,t;
  os=scale
  if(cf_max){
    # cf.bc is present!
    .=cf_new(cf[],y);if(scale(cf[0]))return -2;
    .=frac_from_cf(f[],cf[],1)
    d=f[0];scale=0;if(f[1]%2==0)d=-d;scale=os
   return d
  }
  oib=ibase;ibase=A
  scale=0
   es=3*os/4
  scale=os
   eps=A^-es
   y+=eps/A
  scale=es
   y/=1
  scale=0
  if(y<0)y=-y
  d=y-(n=y/1)
  if(d<eps){t=2*(n%2)-1;scale=os;ibase=oib;return t}#integers are x/1
  t=y/2;t=y-t-t
  # Find numerator and denominator of fraction, if any
  lim=A*A;max2=A^5*(max=A^int(os/2));p=1
  i=0;y=t
  while(1) {
    scale=es;y=1/y;scale=0
    y-=(t=cf[++i]=y/1);p*=1+t
    if(i>lim||(max<p&&p<max2)){cf[i=1]=-2;break}#escape if number seems irrational    
    if((p>max2||3*length(t)>es+es)&&i>1){cf[i--]=0;break}#cheat: assume rational
    if(y==0)break;#completely rational
  }
  n=1;d=cf[i]
  if(i==0){print "id_frac2_: something is wrong; y=",y,", d=",d,"\n"}
  if(d!=-2&&i)while(--i){d=n+cf[i]*(t=d);n=t}
  if(d<A^os){d*=2*(n%2)-1}else{d=-2}
  scale=os;ibase=oib
  return d;
}

# raise x to integer power y faster than bc's x^y
# . it seems bc (at time of writing) uses
# . an O(n) repeated multiplication algorithm
# . for the ^ operator, which is inefficient given
# . that there is a simple O(log n) alternative:
define fastintpow__(x,y) {
  auto r,hy;
  if(y==0)return(1)
  if(y==1)return(x)
  r=fastintpow__(x,hy=y/2)
  r*=r;if(hy+hy<y)r*=x
  return( r )
}
define fastintpow_(x,y) {
  auto ix,os;
  if(y<0)return fastintpow_(1/x,-y)
  if(y==0)return(1)
  if(y==1)return(x)
  if(x==1)return(1)
  os=scale;scale=0
  if(x==-1){y%=2;y+=y;scale=os;return 1-y}
  # bc is still faster for integers
  if(x==(ix=x/1)){scale=os;return ix^y}
  # ...and small no. of d.p.s, but not for values <= 2
  if(scale(x)<3&&x>2){scale=os;return x^y}
  scale=os;x/=1;scale=0
  x=fastintpow__(x,y);
  scale=os;return x;
}

# Raise x to a fractional power faster than e^(y*l(x))
define fastfracpow_(x,y) {
  auto f,yy,inv;
  inv=0;if(y<0){y=-y;inv=1}
  y-=int(y)
  if(y==0)return 1;
  if((yy=y*2^C)!=int(yy)){x=l(x);if(inv)x=-x;return e(y/1*x)}
  # faster using square roots for rational binary fractions
  # where denominator <= 8192
  x=sqrt(x)
  for(f=1;y&&x!=1;x=sqrt(x))if(y+=y>=1){.=y--;f*=x}
  if(inv)f=1/f;
  return f;
}

# Find the yth root of x where y is integer
define fastintroot_(x,y) {
  auto os,d,r,ys,eps;
  os=scale;scale=0;y/=1;scale=os
  if(y<0){x=1/x;y=-y}
  if(y==1){return x}
  if(y>=x-1){return fastfracpow_(x,1/y)}
  if(y*int((d=2^F)/y)==d){
    r=1;while(r+=r<=y)x=sqrt(x)
    return x
  }
  scale=length(y)-scale(y);if(scale<5)scale=5;r=e(ln(x)/y)
  scale=os+5;if(scale<5)scale=5
  d=1;eps=A^(3-scale)
  ys=y-1
  while(d>eps){
    d=r;r=(ys*r+x/fastintpow_(r,ys))/y
    d-=r;if(d<0)d=-d
  }
  scale=os
  return r/1
}

# Raise x to the y-th power
define pow(x,y) {
 auto os,p,ix,iy,fy,dn,s;
 if(y==0) return 1
 if(x==0) return 0
 if(0<x&&x<1){x=1/x;y=-y}
 os=scale;scale=0
  ix=x/1;iy=y/1;fy=y-iy;dn=0
 scale=os;#scale=length(x/1)
 if(y!=iy&&x<0){
   dn=id_frac2_(y)# -ve implies even numerator
   scale=0;if(dn%2){# odd denominator
     scale=os
     if(dn<0)return  pow(-x,y) # even/odd
     /*else*/return -pow(-x,y) #  odd/odd
   }
   print "pow error: "
   if(dn>0) print "even root"
   if(dn<0) print "irrational power"
   print " of a negative number\n"
   scale=os;return 0
 }
 if(y==iy) {
   if(x==ix){p=fastintpow_(ix,iy);if(iy>0){scale=0;p/=1};scale=os;return p/1}
   scale+=scale;p=fastintpow_(x,iy);scale=os;return p/1
 }
 if((dn=id_frac2_(y))!=-2){ #accurate rational roots (sometimes slower)
   if(dn<0)dn=-dn
   s=1;if(y<0){y=-y;s=-1}
   p=y*dn+1/2;scale=0;p/=1;scale=os
   if(p<A^3)x=fastintpow_(x,p)
   x=fastintroot_(x,dn)
   if(p>=A^3)x=fastintpow_(x,p)
   if(s<0)x=1/x
   return x
 }
 p=fastintpow_(ix,iy)*fastfracpow_(x,fy);
 scale=os+os
 if(ix)p*=fastintpow_(x/ix,iy)
 scale=os
 return p/1
 #The above is usually faster and more accurate than
 # return( e(y*l(x)) );
}

# y-th root of x [ x^(1/y) ]
define root(x,y) {
  return pow(x,1/y)
}

# Specific cube root function
# = stripped down version of fastintroot_(x,3)
define cbrt(x) {
  auto os,d,r,eps;
  if(x<0)return -cbrt(-x)
  if(x==0)return 0
  os=scale;scale=0;eps=A^(scale/3)
  if(x<eps){scale=os;return 1/cbrt(1/x)}
  scale=5;r=e(ln(x)/3)
  scale=os+5;if(scale<5)scale=5
  d=1;eps=A^(3-scale)
  while(d>eps){
    d=r;r=(r+r+x/(r*r))/3
    d-=r;if(d<0)d=-d
  }
  scale=os
  return r/1
}

# Logarithm of x in given base:  log(2, 32) = 5 because 2^5 = 32
#  tries to return a real answer where possible when given negative numbers
#  e.g.     log(-2,  64) = 6 because (-2)^6 =   64
#  likewise log(-2,-128) = 7 because (-2)^7 = -128
define log(base,x) {
  auto os,i,l,sx,dn,dnm2;
  if(base==x)return 1;
  if(x==0){print "log error: logarithm of zero; negative infinity\n";     return  l(0)}
  if(x==1)return 0;
  if(base==0){print "log error: zero-based logarithm\n";                  return    0 }
  if(base==1){print "log error: one-based logarithm; positive infinity\n";return -l(0)}
  scale+=6
  if((-1<base&&base<0)||(0<base&&base<1)){x=-log(1/base,x);scale-=6;return x/1}
  if((-1<x   &&   x<0)||(0<x   &&   x<1)){x=-log(base,1/x);scale-=6;return x/1}
  if(base<0){
    sx=1;if(x<0){x=-x;sx=-1}
    l=log(-base,x)
    dn=id_frac2_(l)
    os=scale;scale=0;dnm2=dn%2;scale=os
    if(dnm2&&dn*sx<0){scale-=6;return l/1}
    print "log error: -ve base: "
    if(dnm2)print "wrong sign for "
    print "implied "
    if(dnm2)print "odd root/integer power\n"
    if(!dnm2){
      if(dn!=-2)print "even root\n"
      if(dn==-2)print "irrational power\n"
    }
    scale-=6;return 0;
  }
  if(x<0){
    print "log error: +ve base: logarithm of a negative number\n"
    scale-=6;return 0;
  }
  x=ln(x)/ln(base);scale-=6;return x/1
}

# Integer-only logarithm of x in given base
# (compare digits function in digits.bc)
define int_log(base,x) { 
 auto os,p,c;
 if(0<x&&x<1) {return -int_log(base,1/x)}
 os=scale;scale=0;base/=1;x/=1
  if(base<2)base=ibase;
  if(x==0)    {scale=os;return  1-base*A^os}
  if(x<base)  {scale=os;return  0    }
  c=length(x) # cheat and use what bc knows about decimal length
  if(base==A){scale=os;return c-1}
  if(base<A){if(x>A){c*=int_log(base,A);c-=2*(base<4)}else{c=0}}else{c/=length(base)+1}
  p=base^c;while(p<=x){.=c++;p*=base}
  scale=os;return(c-1)
}

# Lambert's W function 0 branch; Numerically solves w*e(w) = x for w
# * is slow to converge near -1/e at high scales
define lambertw0(x) {
  auto oib, a, b, w, ow, lx, ew, e1, eps;
  if(x==0) return 0;
  oib=ibase;ibase=A
  ew = -e(-1)
  if (x<ew) {
    print "lambertw0: expected argument in range [-1/e,oo)\n"
    ibase=oib
    return -1
  }
  if (x==ew) {ibase=oib;return -1}
  # First approximation from :
  #   http://www.desy.de/~t00fri/qcdins/texhtml/lambertw/
  #   (A. Ringwald and F. Schrempp)
  # via Wikipedia
  if(x < 0){
    w = x/ew
  } else if(x < 500){
    lx=l(x+1);w=0.665*(1+0.0195*lx)*lx+0.04
  } else if((lx=length(x)-scale(x))>5000) {
    lx*=l(A);w=lx-(1-1/lx)*l(lx)
  } else {
    lx=l(x);w=l(x-4)-(1-1/lx)*l(lx)
  } 
  # Iteration adapted from code found on Wikipedia
  #   apparently by an anonymous user at 147.142.207.26
  #   and later another at 87.68.32.52
  ow = 0
  eps = A^-scale
  scale += 5
  e1 = e(1)
  while(abs(ow-w)>eps&&w>-1){
    ow = w
    if(x>0){ew=pow(e1,w)}else{ew=e(w)}
    a = w*ew
    b = a+ew
    a -= x;
    if(a==0)break
    b = b/a - 1 + 1/(w+1)
    w -= 1/b
    if(x<-0.367)w-=eps
  }
  scale -= 5
  ibase=oib
  return w/1
}

# Lambert's W function -1 branch; Numerically solves w*e(w) = x for w
# * is slow to converge near -1/e at high scales
define lambertw_1(x) {
  auto oib,os,oow,ow,w,ew,eps,d,iters;
  oib=ibase;ibase=A
  ew = -e(-1)
  if(ew>x||x>=0) {
    print "lambertw_1: expected argument in [-1/e,0)\n"
    ibase=oib
    if(x==0)return 1-A^scale
    if(x>0)return 0
    return -1
  }
  if(x==ew) return -1;
  os=scale
  eps=A^-os
  scale+=3
  oow=ow=0
  w=x
  w=l(-w)
  w-=l(-w)
  w+=sqrt(eps)
  iters=0
  while(abs(ow-w)>eps){
    oow=ow;ow=w
    if(w==-1)break
    w=(x*e(-w)+w*w)/(w+1)
    if(iters++==A+A||oow==w){iters=0;w-=A^-scale;scale+=2}
  }
  scale=os;ibase=oib
  return w/1
}

# LambertW wrapper; takes most useful branch based on x
# to pick a branch manually, use lambertw_1 or lambertw0 directly
define w(x) {
  if(x<0)return lambertw_1(x)
  return lambertw0(x)
}

# Faster calculation of lambertw0(exp(x))
# . avoids large intermediate value and associated slowness
# . numerically solves x = y+ln(y) for y
define lambertw0_exp(x) {
  auto oy,y,eps;
  # Actual calculation is faster for x < 160 or thereabouts
  if(x<C*D)return lambertw0(e(x));
  oy=0;y=l(x);y=x-y+y/x;eps=A^-scale
  while(abs(oy-y)>eps)y=x-l(oy=y)
  return y
}

# Shorthand alias for the above
define w_e(x){ return lambertw0_exp(x) }

# Numerically solve pow(y,y) = x for y
define powroot(x) {
  auto r;
  if(x==0) {
    print "powroot error: attempt to solve for zero\n"
    return 0
  }
  if(x==1||x==-1) {return x}
  if(x<=r=e(-e(-1))){
    print "powroot error: unimplemented for values\n  <0";r
    return 0
  }
  r = ln(x)
  r /= w(r)
  return r
}

## Triangular numbers

# xth triangular number
define tri(x) {
  auto xx
  x=x*(x+1)/2;xx=int(x)
  if(x==xx)return(xx)
  return(x)
}

# 'triangular root' of x
define trirt(x) {
  auto xx
  x=(sqrt(1+8*x)-1)/2;xx=int(x)
  if(x==xx)x=xx
  return(x)
}

# Workhorse for following 2 functions
define tri_step_(t,s) {
  auto tt
  t=t+(1+s*sqrt(1+8*t))/2;tt=int(t)
  if(tt==t)return(tt)
  return(t)
}

# Turn tri(x) into tri(x+1) without knowing x
define tri_succ(t) {
  return(tri_step_(t,0+1))
}

# Turn tri(x) into tri(x-1) without knowing x
define tri_pred(t) {
  return(tri_step_(t,0-1))
}

## Polygonal Numbers

# the xth s-gonal number:
#   e.g. poly(3, 4) = tri(4) = 1+2+3+4 = 10; poly(4, x) = x*x, etc
define poly(s, x) {
  auto xx
  x*=(s/2-1)*(x-1)+1;xx=int(x);if(x==xx)x=xx
  return x
}

# inverse of the above = polygonal root:
#   e.g. inverse_poly(3,x)=trirt(x); inverse_poly(4,x)=sqrt(x), etc
define inverse_poly(s, r) {
  auto t,xx
  t=(s-=2)-2
  r=(sqrt(8*s*r+t*t)+t)/s/2;xx=int(r);if(r==xx)r=xx
  return r
}

# converse of poly(); solves poly(s,x)=r for s
#   i.e. if the xth polygonal number is r, how many sides has the polygon?
#   e.g. if the 5th polygonal number is 15, converse_poly(5,15) = 3
#     so the polygon must have 3 sides! (15 is the 5th triangular number)
define converse_poly(x,r) {
  auto xx
  x=2*((r/x-1)/(x-1)+1);xx=int(x);if(x==xx)x=xx
  return x
}

## Tetrahedral numbers

# nth tetrahedral number
define tet(n) { return n*(n+1)*(n+2)/6 }

# tetrahedral root = inverse of the above
define tetrt(t) {
  auto k,c3,w;
  if(t==0)return 0
  if(t<0)return -2-tetrt(-t)
  k=3^5*t*t-1
  if(k<0){print "tetrt: unimplemented for 0<|t|<sqrt(3^-5)\n"; return 0}
  c3=cbrt(3)
  k=cbrt(sqrt(3*k)+3^3*t)
  return k/c3^2+1/(c3*k)-1
}

## Arithmetic-Geometric mean

define arigeomean(a,b) {
  auto c,s;
  if(a==b)return a;
  s=1;if(a<0&&b<0){s=-1;a=-a;b=-b}
  if(a<0||b<0){print "arigeomean: mismatched signs\n";return 0}
  while(a!=b){c=(a+b)/2;a=sqrt(a*b);b=c}
  return s*a
}

# solve n = arigeomean(x,y)
define inv_arigeomean(n, y){
  auto ns,ox,x,b,c,d,i,s,eps;
  if(n==y)return n;
  s=1;if(n<0&&y<0){s=-1;n=-n;y=-y}
  if(n<0||y<0){print "inv_arigeomean: mismatched signs\n";return 0}  
  if(n<y){x=y;y=n;n=x}
  n/=y
  scale+=2;eps=A^-scale;scale+=4
  ns=scale
  x=n*(1+ln(n));ox=-1
  for(i=0;i<A;i++){
    # try to force quadratic convergence
    if(abs(x-ox)<eps){i=-1;break}
    ox=x;scale+=scale
    b=x+x/n*(n-arigeomean(1,x));
    c=b+b/n*(n-arigeomean(1,b));
    d=b+b-c-x
    if(d){x=(b*b-c*x)/d}else{x=b;i=-1;break}
    scale=ns
  }
  if(i!=-1){
    # give up and converge linearly
    x=(x+ox)/2
    while(abs(x-ox)>eps){ox=x;x+=x/n*(n-arigeomean(1,x))}
  }
  x+=5*eps
  scale-=6;return x*y/s
}

Ho mantenuto lo script originale, ma ti consiglio di sostituire la prima riga con

#!/usr/bin/env bc -l

In questo modo si eviterà che la conchiglia si perda e non trovi il bc sulla strada giusta!

funcs.bc chmod +x ./funcs.bcPer utilizzarlo, salvalo con un nome qualsiasi, ad esempio , rendilo eseguibile con ed eseguilo come . Scegli una delle funzioni dello script e riempila di numeri, come la radice cubica di 27 nell’esempio seguente. quit bcDigita per uscire dalla modalità interattiva di ‘s.

./funcs.bc
bc 1.06
Copyright 1991-1994, 1997, 1998, 2000 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
root(27,3)
3.00000000000000000000000000000000000000000000000000
quit

Configurare .bcrc

~/.bcrc Per caricare automaticamente le tue funzioni preferite, crea un file che le contenga tutte. .bcrc Un buon suggerimento per iniziare è quello di https://github.com/idealvin/bc/blob/master/bcrc

pi=4*a(1);
e=e(1);

define sin(x) {
    if (x == pi/2) {
        return 1;
    }

    return s(x);
}

define cos(x) {
    if (x == pi/2) {
        return 0;
    }

    return c(x);
}

define tan(x) {
    if (x == pi/4) {
        return 1;
    }

    if (x == -pi/4) {
        return -1;
    }

    return s(x)/c(x);
}

define cot(x) {
    if (x == pi/4) {
        return 1;
    }

    if (x == -pi/4) {
        return -1;
    }

    return c(x)/s(x);
}

define sec(x) {
    return 1/cos(x);
}

define csc(x) {
    return 1/sin(x);
}

define asin(x) {
    if (x == 1) {
        return pi/2;
    }

    if (x == -1) {
        return -pi/2;
    }

    return a(x/sqrt(1-x^2));
}

define arcsin(x) {
    return asin(x);
}

define acos(x) {
    if (x == 0) {
        return pi/2;
    }

    if (x == 1) {
        return 0;
    }

    if (x == -1) {
        return pi/1;
    }

    if (x > 0) {
        return a(sqrt(1-x^2)/x);
    }

    return pi/1 - acos(-x);
}

define arccos(x) {
    return acos(x);
}

define atan(x) {
    if (x == 1) {
        return pi/4;
    }

    if (x == -1) {
        return -pi/4;
    }

    return a(x);
}

define arctan(x) {
    return a(x);
}

define acot(x) {
    return pi/2-atan(x);
}

define arccot(x) {
    return acot(x);
}

define asec(x) {
    if (x >= 1) {
        return a(sqrt(x^2-1));
    }

    return pi/1 - a(sqrt(x^2-1));
}

define arcsec(x) {
    return asec(x);
}

define acsc(x) {
    if (x == 1) {
        return pi/2;
    }

    if (x == -1) {
        return -pi/2;
    }

    if (x > 1) {
        return a(1/sqrt(x^2-1));
    }

    return -a(1/sqrt(x^2-1));
}

define arccsc(x) {
    return acsc(x);
}

define ln(x) {
    return l(x);
}

define log(a, b) {
    return l(b)/l(a);
}

define lg(x) {
    return log(10, x);
}

define log10(x) {
    return log(10, x);
}

define log2(x) {
    return log(2, x);
}

define pow(a, b) {
    if (scale(b) == 0) {
        return a ^ b;
    }
    return e(b*l(a));
}

define exp(x) {
    return e(x);
}

define cbrt(x) {
    return pow(x, 1/3);
}

define abs(x) {
    if (x < 0) {
        return -x;
    }
    return x;
}

define bessel(n, x) {
    return j(n,x);
}

define a(m, n) {
    if (n < 0) {
        return 0;
    }

    v = 1;
    for (i = 0; i < n; i++) {
        v *= (m - i);
    }
    return v;
}

define fac(n) {
    return a(n, n);
}

define c(m, n) {
    auto v

    if (n < 0) {
        return 0;
    }

    s = scale;
    scale = 0;
    v = a(m, n) / a(n, n);
    scale = s;
    return v;
}

define rad(deg) {
    return deg/180*pi;
}

define deg(rad) {
    return rad/pi*180;
}

.bcrc ~/.bashrcQuindi inserisci il percorso di . BC_ENV_ARGS bc Utilizza la variabile che viene caricata ad ogni avvio. -l bcSuggerisco anche l’opzione , che carica la libreria matematica standard da .

export BC_ENV_ARGS="-l $HOME/.bcrc"

E questo è tutto per ora. Questo e molti altri script con funzioni incredibili possono essere trovati sul sito web phodd.net. Ti consiglio di visitare i seguenti link:

E altre funzioni interessanti per ispirare idee:

Infine, ma non meno importante, il manuale di bc contiene altre informazioni molto importanti per padroneggiare questo strumento.

man bc

Alla prossima volta!

No data was found

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Altri articoli

OpenAI lancia un’estensione rivoluzionaria per sfidare Google

OpenAI ha lanciato un’estensione del browser che mira a sostituire Google come motore di ricerca. Integrando la tecnologia ChatGPT, lo strumento consente di porre domande in linguaggio naturale, offrendo risposte contestualizzate e pertinenti. Grazie alla ricerca semantica avanzata e alla personalizzazione adattiva, l’estensione impara dalle interazioni degli utenti. OpenAI dà inoltre priorità alla privacy, utilizzando la crittografia e le politiche “do-not-track”. L’estensione è disponibile per il download in Chrome, sfidando il dominio di Google sul mercato.

Leggi l'articolo "

Ondata di malware con CAPTCHA falsi

La campagna di malware che utilizza falsi CAPTCHA si sta espandendo rapidamente, rappresentando un rischio crescente per gli utenti. Sfruttando la familiarità degli utenti con i CAPTCHA, i criminali informatici creano pagine che imitano questi meccanismi di sicurezza ma che in realtà distribuiscono pericolosi malware come Lumma e Amadey. Questi programmi compromettono seriamente la sicurezza dei dispositivi e dei dati degli utenti. Questa tecnica mostra l’evoluzione delle tattiche criminali, che ora manipolano elementi web comuni per ingannare le vittime. Questo scenario rafforza la necessità di adottare pratiche di sicurezza rigorose e di sensibilizzare gli utenti per prevenire questi attacchi sempre più sofisticati.

Leggi l'articolo "

Codifica/decodifica degli URL con sed

Esistono vari modi per codificare/decodificare gli url.
In genere i programmatori utilizzano funzioni già pronte per questo scopo.
Ma sai davvero cosa fanno queste funzioni?
Per questo articolo, ho scelto sed come strumento per sostituire i codici e ti indicherò le RFC che trattano l’argomento.

Leggi l'articolo "

Capire come personalizzare VIM su MacOS

Se stai già iniziando a familiarizzare con VIM, è il momento di fare i passi successivi.
In questo articolo ti spiegherò come configurare VIM per MacOS in quello che considero il modo più pulito (potresti volerlo installare in modo diverso e non c’è problema) e come configurare i plugin NerdTree, per accedere all’albero delle directory; Status Tab per inserire alcuni strumenti aggiuntivi sullo schermo (che rendono VIM molto bello); e il plugin Git, per facilitare il controllo delle versioni senza lasciare l’applicazione.
Buona lettura!

Leggi l'articolo "
bureau-it.com