**How to use in Home or CAS:**

**
QPI(number)**

**
Returns a decimal in the form of p/q, (p/q)*pi, sqrt(p/q), e^(p/q), or ln(p/q). The form is based on the size of the denominator q -- the program tries to use the smallest q.**

*Please note that you MUST make two changes in this source. Within the subroutine qpi_out() you must make sure that the line*

if list(3)==2 then s1:=")*π'"; end;

shows the pi symbol after the multiplication symbol. Chances are this forum does not properly handle the unicode. Again, it MUST be the pi symbol and not the word 'pi'.

Also make sure the line

s0:="√("; s1:=")'";

has the sqrt symbol before the ( in s0.

Lastly, you may change qpiEXPLN to whatever cutoff denominator you wish. The default is 50 (minus 1) so as to match the behavior of the original QPI program from the HP48 series.

**BEGIN CODE**

qpi_approx();

qpi_out();

qpi_real();

qpi_root();

qpi_pi();

qpi_ln();

qpi_exp();export qpiEXPLN:=500; // max denom - 1

EXPORT QPI(r)

BEGIN

if r then

qpi_real(r);

else

RETURN(0);

end;

END;qpi_real(r)

BEGIN

local frac;

frac:=qpi_approx(r);if frac(2)<100 then

qpi_out(frac);

else

qpi_root(r,frac);

end;

END;qpi_root(r,frac)

BEGIN

local frac1;if r^2<500001 then

frac1:=qpi_approx(r^2);

if r<0 then frac1(1):=-frac1(1); end;

frac1(3):=1;

if (frac1(2)<1000) AND (frac1(2)<=frac(2)) then

if frac1(2)<10 then

qpi_out(frac1);

else

qpi_pi(r,frac1);

end;

else // sqrt denom not smaller

qpi_pi(r,frac);

end;else // r^2>500000

qpi_pi(r,frac);

end; // end_if r^2<500000

END;qpi_pi(r,frac)

BEGIN

local frac1;if abs(r/pi)<101 then

frac1:=qpi_approx(r/pi);

frac1(3):=2;

if (frac1(2)<1000) AND (frac1(2)<=frac(2)) then

if frac1(2)<10 then

qpi_out(frac1);

else

qpi_ln(r,frac1);

end;

else // (r/pi) denom not smaller

qpi_ln(r,frac);

end;else // abs(r/pi)>100

qpi_ln(r,frac);

end; // end_if abs(r/pi)<101

END;qpi_ln(r,frac)

BEGIN

local frac1,tmp;tmp:=e^(r);

if tmp<1001 then

// check for LN(0)

if tmp then

frac1:=qpi_approx(tmp);

else

frac1:=qpi_approx(MINREAL);

end;

frac1(3):=3;if (frac1(1)*frac1(2)==1) OR (frac1(2)>qpiEXPLN) then

qpi_exp(r,frac);

else

if (frac1(2)<=frac(2)) then

if frac1(2)<10 then

qpi_out(frac1);

else

qpi_exp(r,frac1);

end;

else

qpi_exp(r,frac);

end;end; // end_if p*q==1 or q>50

else // e^(r)>1000

qpi_exp(r,frac);

end; // end_if e^(r)<1001

END;qpi_exp(r,frac)

BEGIN

local frac1;if r<0 then

qpi_out(frac);

elsefrac1:=qpi_approx(LN(r));

frac1(3):=4;

if frac1(2)>qpiEXPLN then

qpi_out(frac);

else

if frac1(2)<=frac(2) then

qpi_out(frac1);

else

qpi_out(frac);

end;

end;end;

END;qpi_out(list)

BEGIN

local s0="(", s1=")'";if list(3)==1 then

s0:="√("; s1:=")'"; // <-- change √ to sqrt symbol

if list(1)<0 then

s0:="'-" + s0;

else

s0:="'" + s0;

end;else

if list(1)<0 then s0:="-" + s0; end;

if list(3) then s1:=")" + s1; end;

if list(3)==2 then s1:=")*π'"; end; // <-- change π to pi symbolcase

if list(3)==3 then s0:="LN(" + s0; end;

if list(3)==4 then s0:="e^(" + s0; end;

end;s0:="'" + s0;

end;

if list(2)==1 then

expr(s0 + abs(list(1)) + s1);

else

expr(s0 + abs(list(1)) + "/" + list(2) + s1);

end;END;

qpi_approx(r)

BEGIN

local num,inum,den,iden;

local p0,q0,p1,q1,p2,q2;

local quo,rem,digs=9;if NOT(r) then RETURN({0,1,0}); end;

num:=abs(r);

inum:=IP(num);

den:=1;while num-inum do

num:=num*10;

den:=den*10;

inum:=IP(num);

end;iden:=den;

rem:=den; den:=num;

p1:=0; p2:=1;

q1:=1; q2:=0;repeat

p0:=p1; p1:=p2;

q0:=q1; q1:=q2;

num:=den; den:=rem;

quo:=IP(num/den);

rem:=num MOD den;

p2:=quo*p1+p0;

q2:=quo*q1+q0;

until 10^digs*abs(inum*q2-iden*p2)<iden*p2 end;if (r>0) then

RETURN({p2,q2,0});

else

RETURN({-p2,q2,0});

end;END;

*Edited: 9 Nov 2013, 10:46 p.m. after one or more responses were posted*