Temps de lecture estimé : 15 minutes
Modes d’utilisation
Commençons par le commencement.
bc
Pour commencer, il est important de savoir qu’il y a deux façons de l’utiliser : le mode interactif et le mode non interactif.
bc
L’utilisation du mode interactif est facile, il suffit de taper et de lancer les commandes.
$ 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
En mode non-interactif, vous devez passer une chaîne de caractères au stdin du bc d’une manière ou d’une autre. echo, printf, pipe, ici les chaînes… choisissez la plus pratique et allez-y. Voyons quelques exemples :
$ echo "10*10" | bc #via pipe 100
$ bc <<< "10-3" #via here strings 7
Variables
bc
possède 4 variables importantes qu’il utilise en interne :
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
Vous pouvez également définir vos propres variables, mais toujours en minuscules.
$ 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
Le bc ne tolère pas de bins élevés dans les variables, mais il exige des bins élevés pour toutes les entrées hexadécimales ! Soyez-en conscient =)
Conversions hexadécimales, décimales, octales, binaires et similaires…
Cette calculatrice devient encore plus intéressante lorsqu’il s’agit de changer de base. Par exemple, pour convertir l’hexadécimal (base 16) en décimal (base 10), il suffit de modifier les variables ibase (entrée) et obase (sortie). Les deux sont à 10 par défaut. Changeons donc simplement ibase, puisque la sortie sera décimale par défaut :
$ echo "ibase=16; FF" | bc 255
ibase
obase
Ou pour convertir la base 16 (hexadécimale) en base 2 (binaire) avec les arguments (entrée) et (sortie) déclarés ensemble :
$ echo "ibase=16; obase=2; FF" | bc 11111111
Opérateurs
L’essentiel :
+ addition – soustraction * multiplication / division % reste ^ puissance
Voici bc en action avec quelques commandes et mes commentaires à côté (oui, il accepte les commentaires en utilisant # après chaque commande).
bc
Pour entrer en mode interactif, il suffit d’appeler la commande .
$ 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
Autres fonctions
Vous avez besoin de plus ? Logarithme, sinus, cosinus, tangente, etc. Utilisez la bibliothèque mathématique bc avec l’option –mathlib
$ bc --mathlib s(1) .84147098480789650665 c(1) .54030230586813971740 a(1) .78539816339744830961
Et le bc peut même faire des programmes !
Voyez cet exemple tiré du manuel de bc, le chéquier.
Enregistrez le code ci-dessous dans un fichier quelconque, par exemple 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
Exécutez-le maintenant.
$ 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
Il existe de nombreuses autres fonctions dans le bc, qui valent la peine d’être explorées si vous souhaitez approfondir le sujet. Le manuel du bc est très intéressant, il vaut certainement la peine d’y jeter un coup d’œil.
Mais avant de terminer l’article, jetez un coup d’œil à cette énorme archive de fonctions 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 }
J’ai conservé le script original, mais je vous recommande de remplacer la première ligne par
#!/usr/bin/env bc -l
Cela évitera que l’obus ne se perde et ne trouve pas la bc sur le bon chemin !
funcs.bc
chmod +x
./funcs.bc
Pour l’utiliser, enregistrez-le sous n’importe quel nom, tel que , rendez-le exécutable avec et exécutez-le en tant que .
Choisissez l’une des fonctions du script et remplissez-la avec des nombres, comme la racine cubique de 27 dans l’exemple ci-dessous.
quit
bc
Tapez pour quitter le mode interactif de ‘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
Configuration du fichier .bcrc
~/.bcrc
Pour charger automatiquement vos fonctions préférées, créez un fichier qui les contiendra toutes.
.bcrc
Une bonne suggestion pour commencer votre fichier est 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
~/.bashrc
Saisissez ensuite le chemin d’accès à votre .
BC_ENV_ARGS
bc
Utilisez la variable qui est chargée à chaque démarrage.
-l
bc
Je vous suggère également l’option , qui charge la bibliothèque mathématique standard à partir de .
export BC_ENV_ARGS="-l $HOME/.bcrc"
Et c’est tout pour l’instant. Vous trouverez ce script et bien d’autres avec des fonctions incroyables sur le site phodd.net. Je vous recommande de visiter les liens suivants :
Et d’autres fonctions intéressantes pour inspirer des idées :
- http://x-bc.sourceforge.net/extensions_bc.html
- http://x-bc.sourceforge.net/scientific_constants_bc.html
Enfin, le manuel de bc contient d’autres informations très importantes pour maîtriser cet outil.
man bc
A la prochaine fois !