The Museum of HP Calculators

HP Forum Archive 21

[ Return to Index | Top of Index ]

QPI for HP Prime
Message #1 Posted by Han on 3 Nov 2013, 11:50 p.m.

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

      
Re: QPI for HP Prime
Message #2 Posted by Han on 4 Nov 2013, 12:04 a.m.,
in response to message #1 by Han

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.

            
Re: QPI for HP Prime
Message #3 Posted by CompSystems on 5 Nov 2013, 11:20 a.m.,
in response to message #2 by Han

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.

                  
Re: QPI for HP Prime
Message #4 Posted by Han on 5 Nov 2013, 12:24 p.m.,
in response to message #3 by CompSystems

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.

                  
Re: QPI for HP Prime
Message #5 Posted by Olivier Lecluse on 6 Nov 2013, 10:46 a.m.,
in response to message #3 by CompSystems

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/


                        
Re: QPI for HP Prime
Message #6 Posted by Han on 6 Nov 2013, 5:41 p.m.,
in response to message #5 by Olivier Lecluse

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?

                              
Re: QPI for HP Prime
Message #7 Posted by Olivier Lecluse on 7 Nov 2013, 12:39 p.m.,
in response to message #6 by Han

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

                                    
Re: QPI for HP Prime
Message #8 Posted by Han on 7 Nov 2013, 2:19 p.m.,
in response to message #7 by Olivier Lecluse

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.

                                          
Re: QPI for HP Prime
Message #9 Posted by Harold A Climer on 8 Nov 2013, 7:24 p.m.,
in response to message #8 by Han

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.

                                                
Re: QPI for HP Prime
Message #10 Posted by Joe Horn on 8 Nov 2013, 11:37 p.m.,
in response to message #9 by Harold A Climer

Strange; your two examples work for me:

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

                                                
Re: QPI for HP Prime
Message #11 Posted by Han on 9 Nov 2013, 8:59 a.m.,
in response to message #9 by Harold A Climer

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.

                                          
Re: QPI for HP Prime
Message #12 Posted by Olivier Lecluse on 9 Nov 2013, 2:41 a.m.,
in response to message #8 by Han

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.

                                                
Re: QPI for HP Prime
Message #13 Posted by Olivier Lecluse on 9 Nov 2013, 4:53 a.m.,
in response to message #12 by Olivier Lecluse

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;

                                                
Re: QPI for HP Prime
Message #14 Posted by Han on 9 Nov 2013, 6:07 p.m.,
in response to message #12 by Olivier Lecluse

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.

                                          
Re: QPI for HP Prime
Message #15 Posted by Timothy Roche on 9 Nov 2013, 7:53 p.m.,
in response to message #8 by Han

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

                                                
Re: QPI for HP Prime
Message #16 Posted by Han on 9 Nov 2013, 8:24 p.m.,
in response to message #15 by Timothy Roche

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.

                                                      
Re: QPI for HP Prime
Message #17 Posted by Timothy Roche on 9 Nov 2013, 10:39 p.m.,
in response to message #16 by Han

Making that change in the code worked.

QPI(.123) = 123/1000.

Tim


[ Return to Index | Top of Index ]

Go back to the main exhibit hall