QPI for HP Prime



#2

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);
else

frac1:=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:="&#8730;("; s1:=")'"; // <-- change &#8730; 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:=")*&#960;'"; end; // <-- change &#960; to pi symbol

case
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


#3

Please also note this only works (currently) for real numbers. I will probably update it later on to work with complex numbers, lists, arrays, etc.


#4

congratulations, great code

this algorithm should replace the function of the key: [a <-> b / c] are agree or not?

examples


// #1 real numbers

QPI(1.57) ==> 157/100

ã(1.2) ==> 1.09544511501

QPI(Ans) ==> ã(6/5)

pi/2.7 ==> 1.16355283466

QPI(Ans) ==> (10/27)*ƒÎ

// #2 complex numbers

QPI(ã(1.2)+4.5*i) ==> ã(6/5)+(9/2)*i

QPI((1,1.16355283466)) ==> 1+(10/27)*ƒÎ*i

// #3 lists

QPI({3.5,1.57}) ==> { 7/2, 157/100 }

mylist:={{&#8722;.714285714286,&#8722;1.41421356237},{&#8722;.405465108108,1.11751906874},{&#8722;2.44346095279,.657047293577}}

QPI(mylist) ==>

{ {-(5/7),-ã(2)}, {LN((2/3)),e^(1/9)}, {-(7/9)*ƒÎ,ã(275/637)} }

spanish forum

http://www.adictoshp.org/topic/545-qpi/


Edited: 5 Nov 2013, 11:24 a.m.


#5

I don't know if the developers will incorporate this into firmware, but at the least we should be able to make QPI() a replacement for the [a b/c] key with users keys. Unfortunately, user keys do not work properly -- some keys cannot be redefined even when properly coded. The [a b/c] is one of them, among many others.

#6

Thank you for this great program. I used it on HP48 and I missed it on the prime.

I have some trouble copying the program on the prime though. I used the qpi2.txt file linked below and I have an error message when i try 27^0.5 : Incorrect argument type but for 3Pi/2 or fractions, , it works.

Any idea how I could solve this issue ?

Quote:

http://www.adictoshp.org/topic/545-qpi/



#7

Quote:
Thank you for this great program. I used it on HP48 and I missed it on the prime.

I have some trouble copying the program on the prime though. I used the qpi2.txt file linked below and I have an error message when i try 27^0.5 : Incorrect argument type but for 3Pi/2 or fractions, , it works.

Any idea how I could solve this issue ?


I tried QPI(27^.5) and got 3*sqrt(3) on my calculator. Would you mind checking a few things for me?

1. When you copied the program, did you copy the contents of qpi2.txt using a text editor that supports unicode?

2. Could you share your settings that you used to get this error?


#8

Thank you for your answer.
To transfert the qpi2.txt program, I opened it with geany on windows, then I made a copy/paste into a new program in the emulator.

I tried different settings (RPN which is my default one, Textbook, Algebraic) and I got the same error.
I tried to reset all the content and settings of the emulator but i got the same message with radicals. It works with fractions or fractions of Pi.

Maybe I did something wrong with the transfert of qpi2.txt to the calculator or Maybe my qpi2.txt is altered ? Here is my md5sum for the qpi2 file
MD5 (qpi2.txt) = 5b83602a45206f7d168acfea1b8bfb9e


#9

I think the problem is likely due to conversions of special characters. If you will send me an email through the forums, I will send you the program with exact directions on how to get the program to work.

The other thing you could try is to use Notepad (not gleany) to copy/paste the qpi2.txt file.


#10

I like your program,but there is an odd response when certain decimal numbers are used. It does not respond with a the two integers one would expect. For example if I type in 0.123 or even 0.123123123123 etc a few lines of code are displayed as a result, not the ratio of the two numbers that represent the quotient, 0.25 give 1/4 0.5 gives 1/2 OK.
I am sure other decimals give a similar strange results,but I have not had a lot of time exploring what the are.


#11

Strange; your two examples work for me:

Did you make the necessary two changes in the source code (the square root and pi symbols)?

#12

Quote:
I like your program,but there is an odd response when certain decimal numbers are used. It does not respond with a the two integers one would expect. For example if I type in 0.123 or even 0.123123123123 etc a few lines of code are displayed as a result, not the ratio of the two numbers that represent the quotient, 0.25 give 1/4 0.5 gives 1/2 OK.
I am sure other decimals give a similar strange results,but I have not had a lot of time exploring what the are.

Could you please post a screenshot of what is being displayed? This would help me figure out what causes the issues you are having.

#13

I finally figured out what was wrong with radicals giving an error message : The problem is with the initialization of qpiMAXINT variable.
If i change qpiMAXINT=2^20 to qpiMAXINT=1048576, the QPI program works just fine with radicals for me.

I think it is a settings problem, as the test nodd>qpiMAXINT when qpiMAXINT=2^20 is not evaluated as 0 ou 1 but returns 2>2^20 and then gives a bad argument type error. If I change nodd>qpiMAXINT with eval(nodd>qpiMAXINT) the program works fine too but I prefered to change the qpiMAXINT initialization to qpiMAXINT=1048576

but I don't know which setting is involved in that behaviour but I guess other people could be affected with this issue.


#14

I have made a program similar to Qpi but searching for another pattern : it tries to match this type of expression : (A+sqrt(R))/D or square root of this.

There is no miracle here and it cannot find radicals when numbers are too big, but with quite simple numbers, it works fine.

The program can be downloaded

The program can be found here (hpprgm format)

ToRadical.hpprgm

Or in plain text version

// ToRadical by Olivier Lecluse
// Try to convert nbr into (A+sqrt(R))/D
// or sqrt((A+sqrt(R))/D)

export trDIGITS:=8;
export trMAXINT:=100; // Don't push this one too much !
epsilon:=ALOG(-trDIGITS);

torad();

torad(nbr)
BEGIN
LOCAL signe,locy,locf;
LOCAL Bij,Dmax;

locf:=1;

Bij:=1;
Dmax:=0;
D:=1;
A:=0;

WHILE Bij<trMAXINT*(trMAXINT+1) AND locf>epsilon DO

IF (D=1) OR (A&#8805;trMAXINT) THEN
Dmax:=Dmax+1;
D:=min(Dmax,trMAXINT);
A:=Dmax-D;
ELSE
D:=D-1;
A:=A+1;
END;

FOR signe FROM &#8722;1 TO 1 STEP 2 DO
locy:=ROUND(2*signe*A*D*nbr-D²*nbr²,trDIGITS);
locf:=ABS(FP(locy));
IF locf<epsilon THEN
BREAK;
END;
END;//FOR

Bij:=Bij+1;
END; // While

A:=A*signe;
R:=ROUND((D*nbr-A)²,trDIGITS);
END;

EXPORT ToRadical(nbr)
BEGIN
LOCAL a1,d1,r1,ok;
torad(nbr);
a1:=A;
d1:=D;
r1:=R;
ok:=0;
IF A+D+&#8730;(R)>4*trMAXINT THEN // convert all the &#8730; codes into a squareroot
trMAXINT:=200;
torad(nbr²);
IF A+D+&#8730;(R)<a1+d1+&#8730;(r1) THEN // Here
ok:=1;
CASE
IF ABS((A+&#8730;R)/D-nbr²)<epsilon and nbr>0 THEN RETURN(CAS.simplify(&#8730;((A+&#8730;R)/D))); END; // Here
IF ABS((A-&#8730;R)/D-nbr²)<epsilon and nbr>0 THEN RETURN(CAS.simplify(&#8730;((A-&#8730;R)/D))); END; // Here
IF ABS((A+&#8730;R)/D-nbr²)<epsilon and nbr<0 THEN RETURN(CAS.simplify(&#8722;&#8730;((A+&#8730;R)/D))); END; // Here
IF ABS((A-&#8730;R)/D-nbr²)<epsilon and nbr<0 THEN RETURN(CAS.simplify(&#8722;&#8730;((A-&#8730;R)/D))); END; // Here
DEFAULT RETURN("Oooops");
END; //CASE
END; // IF sqr better
END; // IF calc sqr
IF ok=0 THEN
CASE
IF ABS((A+&#8730;R)/D-nbr)<epsilon THEN // Here
RETURN(CAS.simplify((A+&#8730;R)/D)); END; // Here
IF ABS((A-&#8730;R)/D-nbr)<epsilon THEN RETURN(CAS.simplify((A-&#8730;R)/D)); END; // Here
DEFAULT RETURN("Oooops");
END; // CASE
END; // IF

END;

#15

Quote:
I finally figured out what was wrong with radicals giving an error message : The problem is with the initialization of qpiMAXINT variable.
If i change qpiMAXINT=2^20 to qpiMAXINT=1048576, the QPI program works just fine with radicals for me.

I think it is a settings problem, as the test nodd>qpiMAXINT when qpiMAXINT=2^20 is not evaluated as 0 ou 1 but returns 2>2^20 and then gives a bad argument type error. If I change nodd>qpiMAXINT with eval(nodd>qpiMAXINT) the program works fine too but I prefered to change the qpiMAXINT initialization to qpiMAXINT=1048576

but I don't know which setting is involved in that behaviour but I guess other people could be affected with this issue.


I can confirm this behavior in firmware 5106. There may have even been a reference to this issue in previous threads here... but I have not been able to dig it up.

#16

I have the same or similar run-time error as Harold describes. Executing QPI(.123) yields the following line if code as output:

IF 0 OR frac1(2)>50-1 THEN qpi_exp(r,frac) ELSE IF (frac1(2)<=frac(2)) THEN IF frac1(2)<10 THEN qpi_out(frac1) ELSE qpi_exp(r,frac) END END

I copied the QPI source listing from Han's previous post into the emulator and edited the special characters for sqrt and pi where Han indicated in his comments.

Tim


#17

Quote:
I have the same or similar run-time error as Harold describes. Executing QPI(.123) yields the following line if code as output:

IF 0 OR frac1(2)>50-1 THEN qpi_exp(r,frac) ELSE IF (frac1(2)<=frac(2)) THEN IF frac1(2)<10 THEN qpi_out(frac1) ELSE qpi_exp(r,frac) END END

I copied the QPI source listing from Han's previous post into the emulator and edited the special characters for sqrt and pi where Han indicated in his comments.

Tim


If you change qpiEXPLN:=50-1; near the top of the source code to qpiEXPLN:=50; does it fix the error? I think there is a bug in how global variables get initialized. It seems that the initialization does not actually evaluate the expression.

Edited: 9 Nov 2013, 8:26 p.m.


#18

Making that change in the code worked.

QPI(.123) = 123/1000.

Tim


Possibly Related Threads...
Thread Author Replies Views Last Post
  [HP-PRIME] QPI project CompSystems 0 127 10-09-2013, 02:51 PM
Last Post: CompSystems
  hp50g Getting \->Qpi to work in a custom menu Rich Messeder (US) 1 131 02-07-2007, 08:54 PM
Last Post: Rich Messeder (US)
  QPI for the HP-42S Erik Ehrling (Sweden) 7 329 09-03-2003, 02:10 PM
Last Post: Erik Ehrling (Sweden)
  QPI for HP42S Erik Ehrling (Sweden) 0 92 11-03-2002, 06:29 PM
Last Post: Erik Ehrling (Sweden)
  Erik Ehrling (Sweden) and QPI for HP-42S erwin 1 134 10-30-2002, 06:11 AM
Last Post: Erik Ehrling (Sweden)

Forum Jump: