[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: хороший калькулятор



Ed <spied@yandex.ru> writes:

> bc сейчас и пользую, претензии есть. во-первых работа с разными
> основаниями счисления неудобна, во-вторых не раз натыкался на:
> 2^(1/2)
> Runtime warning (func=(main), adr=9): non-zero scale in exponent
> 1

Ну так в документации явно написано, что показатель степени должен быть
целочисленным. Для возведения в произвольную степень надо написать
функцию "e в степени ln".

Вот полезняшка есть funcs.bc. Выложу весь файлик сюда. Он не такой
длинный. Стартовать можно так bc -ql funcs.bc. В сети можно взять всякие
пеобразования еще типа из разных величин: унции, мм, градусы и т. д. Тут
найдешь функцию pow (x, y).



### 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=20;
define pi(){return(a(1)*4)}         ; pi  = pi()
                                      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
define resetbase() { ibase=1+1+1+1+1+1+1+1+1+1;obase=ibase; }
d0=0;d1=1;d2=2;d3=3;d4=4;d5=5;d6=6;d7=7;d8=8;d9=9
d10=10;d11=11;d12=12;d13=13;d14=14;d15=15;d16=16;d17=17;d18=18;d19=19
d20=20;d21=21;d22=22;d23=23;d24=24;d25=25;d26=26;d27=27;d28=28;d29=29
d30=30;d31=31;d32=32;d33=33;d34=34;d35=35;d36=36;d37=37;d38=38;d39=39

### 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 xx;xx=int(x);if(xx>x)xx-=1;return(xx) }

# Round up to integer above x
define ceil(x) { return(-floor(-x)) }

# Fractional part of x:  12.345 -> 0.345
define frac(x) { return(x-floor(x)) }

# 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 rup(x,y) { return(y*ceil(x/y)) }

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

# Round x to the nearest multiple of y
define rnd(x,y) { return(y*floor(x/y+.5)) }

# Find the remainder of x/y
define rem(x,y) { return(x-rdn(x,y)) }

# Greatest common divisor of x and y
define gcd(x,y) { auto r;while(y>0){r=rem(x,y);x=y;y=r};return(x) }

# Lowest common multiple of x and y
define lcm(x,y) { return (x*y/gcd(x,y)) }

# Output function - prints a and b as a fraction in smallest terms
define sft(a,b) { #smallest fractional terms
  auto c,d,e
  c=gcd(a,b);
  d=int(a/c);
  e=int(b/c);
  print a,"/",b," = ",d,"/",e,"\n";
  return(d/e)
}

### Exponential / Logs / Trig

# Raise x to the y-th power
define pow(x,y) {
 auto yy;yy=int(y)
 if (y==yy) { return(x^yy); }
 return( e(y*l(x)) );
}

# y-th root of x [ x^(1/y) ]
define root(x,y) {
 auto iy,iyy;
 iy=1/y;iyy=int(iy)
 if (iy==iyy) { return(x^iyy); }
 scale+=5;y=e(l(x)/y);scale-=5;y=y/1+10^-scale
 x=int(y);if(x==y)y=x
 return( y );
}

# workhorse function for powrem
define powrem_(x,y,m) {
  auto r, y2;
  if(y==0)return(1)
  if(y==1){if(x<m){return(x)}else{return(x-m*(x/m))}}
  y2=y/2
  r=powrem_(x,y2,m); if(r>=m)r%=m
  r^=2             ; if(r>=m)r%=m
  if(2*y2!=y){r*=x ; if(r>=m)r%=m}
  return( r )
}

# Raise x to the y-th power, modulo m
define powrem(x,y,m) {
  auto os,r;
  os=scale;scale=0
  if(x<0){
    print "powrem: base is negative, rectifying...\n"
    x*=-1
  }
  if(x!=x/1){
    print "powrem: base is not an integer, truncating...\n"
    x/=1
  }
  if(y<0){
    print "powrem: exponent is negative, rectifying...\n"
    y*=-1
  }
  if(y!=y/1){
    print "powrem: exponent is not an integer, truncating...\n"
    y/=1
  }
  if(m<0){
    print "powrem: modulus is negative, rectifying...\n"
    m*=-1
  }
  if(m!=m/1){
    print "powrem: modulus is not an integer, truncating...\n"
    m/=1
  }
  if(m==0){
    print "powrem: modulus is zero - doing full calculation!\n"
    return x^y
  }
  r=powrem_(x,y,m)
  scale=os
  return( r )
}

# Logarithm of y, base x:  log(2, 32) = 5 because 2^5 = 32
define log(x,y) { return(l(y)/l(x)) }

# Sine
#efine s(x) { predefined }
# Cosine
#efine c(x) { predefined }
# Tangent
define t(x) { auto c;c=c(x);if(c==0)c+=10^-scale;return(s(x)/c) }

# Secant
define sc(x) { return(1/s(x)) }
# Cosecant
define cs(x) { return(1/c(x)) }
# Cotangent
define ct(x) { auto s;s=s(x);if(s==0)s+=10^-scale;return(c(x)/s) }

# Arcsine
define as(x) { if(abs(x)==1)return(2*a(1)*x)else return( a(x/sqrt(1-x^2)) ) } 
# Arccosine
define ac(x) { return 2*a(1)-as(x) }

# Arctangent (one argument)
#efine a(x)  { single argument arctangent is predefined }

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

# Arcsecant
define asc(x) { return( a(x/sqrt(x^2-1)) ) }
# Arccosecant
define acs(x) { return( asc(x)+2*a(1)*(sgn(x)-1) ) }
# Arctangent
define act(x) { return( a(x)+2*a(1) ) }

# Hyperbolic Sine
define sh(x) { auto t;t=e(x);return((t-1/t)/2) }
# Hyperbolic Cosine
define ch(x) { auto t;t=e(x);return((t+1/t)/2) }
# Hyperbolic Tangent
define th(x) { auto t;t=e(2*x)-1;return(t/(t+2)) }

# Hyperbolic Secant
define sch(x) { return(1/ch(x)) }
# Hyperbolic Cosecant
define csh(x) { return(1/sh(x)) }
# Hyperbolic Cotangent
define cth(x) { return(1/th(x)) }

# Hyperbolic Arcsine
define ash(x) { return( l(x+sqrt(x^2+1)) ) }
# Hyperbolic Arccosine
define ach(x) { return( l(x+sqrt(x^2-1)) ) }
# Hyperbolic Arctangent
define ath(x) { return( l((1+x)/(1-x))/2 ) }

# Hyperbolic Arcsecant
define asch(x) { return( l((sqrt(1-x^2)+1)/x) ) }
# Hyperbolic Arccosecant
define acsh(x) { return( l((sqrt(1+x^2)*sgn(x)+1)/x) ) }
# Hyperbolic Arccotangent
define acth(x) { return( l((x+1)/(x-1))/2 ) }

define grad(x) { auto s;s=s(a(1)-x);if(s==0)s+=10^-scale;return(s(x)/s) }
define agrad(x) { return( x/sqrt(1+x^2) ) }
define chord(x)  { return( 2* s(x/2) ) }
define achord(x) { return( 2*as(x/2) ) }

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

### 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)return(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))
}

### Fibonacci

# n-th Fibonacci number
define fib(x){
  auto a,b,c,os
  os=scale;scale=0;x/=1
  a=0;b=1;c=1
  if(x<0){scale=os;return(fib(-x)*((-1)^(1-x)))}
  if(x==0){scale=os;return(0)}
  while(--x){
    c=a+b;a=b;b=c
  }
  scale=os;return(c)
}

define fibf(n) { return( (pow(phi,n)-pow(psi,n))/sqrt(5) ) }

# n-th Lucas number
define luc(x){
  auto a,b,c,os
  os=scale;scale=0;x/=1
  a=2;b=1;c=3
  if(x<0){scale=os;return(luc(-x)*((-1)^(-x)))}
  if(x==0){scale=os;return(2)}
  if(x==1){scale=os;return(1)}
  while(--x){
    c=a+b;a=b;b=c
  }
  scale=os;return(c)
}

define lucf(n) { return( pow(phi,n)+pow(psi,n) ) }

### Factorials

# x!
define factorial(x) {
 auto i,xx
 if(x<0)return(0)
 if(x<2)return(1)
 xx=1;for(i=x;i>=1;i--)xx*=i
 return(xx)
}

# Gosper's approximation to the natural log of n!
define gosper(n) { return(  n*(l(n)-1) + ( l(2*n+1/3)+ l(pi()) )/2  ) }

# Gosper's approximation to n!
define gfactorial(n) { return ceil(e(gosper(n))) }

# logarithm of x!
define lnfactorial(x) {
 auto i,xx,max
 if(x<0)return(-10^100)
 if(x<2)return(0)
 max=2500 # Arbitrary large value
 if(x<max)return( l(factorial(x)) )
 xx=l(factorial(max))
 for(i=x;i>max;i--)xx+=l(i)
 return(xx)
}

# Number of permutations of r items from a group of n
define permutation(n,r) {
 auto i,p
 if(n<0||r<0||r>n)return(0)
 p=1;for(i=n;i>n-r;i--)p*=i
 return(p)
}

# Number of combinations of r items from a group of n
define combination(n,r) {
 if(n<0||r<0||r>n)return(0)
 if(2*r>n)r=n-r
 return( permutation(n,r)/factorial(r) ) 
}

# y-th factorial of x: x!_y
define multifactorial(y,x) {
 auto i,xx;
 xx=1;for(i=x;i>=1;i-=y)xx*=i
 return(xx);
}

### Digit related functions

# The base ten number created by appending the base ten numbers
# from 1 to x, i.e. 1, 12, 123, ..., 123456789101112, etc.
define dc(x) {
 if (x<=0) return(0);
 return(x+dc(x-1)*10^int(1+log(10,x)));
}

# Sum of digits in a number: 1235 -> 11.   ibase modifies base used
define digitsum(x) { 
 auto os,xx,t;
 os=scale;scale=0
 t=0;while(x>=1){ xx=x/ibase;t+=x-xx*ibase;x=xx }
 scale=os
 return(t)
}

# Product of digits+1 less #digits
# e.g. 235 -> (2+1)(3+1)(5+1)-3 = 3*4*6 - 3 = 69
define digitprod(x) { 
 auto os,xx,t,c;
 os=scale;scale=0
 t=1;c=0;while(x>=1){ xx=x/ibase;t*=(x-xx*ibase+1);x=xx;c+=1 }
 scale=os
 return(t-c)
}

# Number of digits in the base 'ibase' representation of x
define digits(x) { 
 auto os,c;
 if(x<0)return(digits(-x))
 if(x==0||x==1)return(1)
 os=scale;scale=10
  c=ceil(log(ibase,x))-3;if(c<0)c=0
 scale=0
  x/=ibase^c
  while(x){c+=1;x/=ibase}
 scale=os
 return(c)
}

# Reverse the digits in x (use ibase)
define reverse(x) {
  auto os,y;
  os=scale;scale=0
  y = 0
  while(x) {
    y = ibase*y + x%ibase
    x /= ibase
  }
  scale=os
  return(y) 
}

### Formatted output

# workhorse function for expnot and engnot
define ezznot_(x,f,z) {
  auto m, e, ms, es, l10, os, ns;
  os=scale ; ns=scale+6 ; scale=ns
  ms = 1
  if (x < 0) { ms = -1 ; x *= -1 }

  l10 = l(10)
  x = l(x)/l10
  es = 1
  if (x < 0) { es = -1 ; x *= -1 }

  scale=0
    e = x/z; if(es==-1)e+=1 ; e*=z
  scale=ns
    m = e(l10*es*(x-e)) + 10^-(os+1)
  scale=f
    m /= 1
  scale=os

  print ms*m,"*10^"
  return(es*e)
}

# Exponential notation - display x in the form a.bbbbbbb*10^cc
define expnot(x,f) { # f = sig. fig.
  return ezznot_(x,f,1)
}

# Engineering notation - display x in the form a.bbbbbbb*10^cc
# where cc is a multiple of 3
define engnot(x,f) { # f = sig. fig.
  return ezznot_(x,f,3)
}

# Truncate trailing zeroes from a scaled number
define trunc(x) {
  auto os,i;os=scale
  for(i=0;i<=os;i++){
    scale=i
    if(x==x/1){
      x=x/1
      scale=os
      return(x)
    }
  } 
}

# Print an integer in a field width
define intprint(n, w){ # w is field width
 auto os,m,i;
 os=scale;scale=0;n/=1
 m=n;w+=(m!=0);if(m<0){m*=-1;w-=1}
 for(;m>0;w--){m/=10}
 for(i=1;i<w;i++)print " "
 scale=os;return(n)
}
#print "funcs.bc loaded\n";


Reply to: