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: