[comp.sys.handhelds] DEC2FRAC-II for the HP48SX

sjthomas@cup.portal.com (Stephen J Thomas) (03/27/91)

*** HP 48SX ***

First, congratulations to Joe Horn for his recently posted algorithm
which improves on the ->Q function of the HP48.  Joe's program (which
he calls DEC2FRAC, and I call TO.Q, requires two inputs:

    2:  real number to be "fractionalized"
    1:  maximum value of the denominator

By specifying the maximum denominator, the user can greatly control 
the output of the program.  However, if you're performing many 
computations which all involve the same maximum denominator, it is 
tiresome to have to repeatedly re-enter this denominator.

I've written a small calling program which allows you to maintain the 
same denominator.  This is done by entering the maximum denominator 
only when you wish to change it -- and in that case, it must be the 
only element in a list in level one.  That is, on executing the 
calling program (which I call TO.Q2), if level 1 contains a list, the 
value in the list is stored into a global variable named 'denom'.  
Then 'denom' is recalled to level 1, and execution dumps into TO.Q. 

If, on executing TO.Q2, level 1 contains a real number (actually, 
anything other than a list), 'denom' is recalled to level 1, and 
execution continues with TO.Q.

Example:  What are the best fractional approximations for e and the
          square root of 2 ( v/2 ) with a maximum denominator of 100?
  
   Solution:  First do e:  1  EXP  { 100 }   TO.Q2   ==>  '193/71'

              Now do v/2:  Since the max denom is the same, just
                           enter v/2:
                                      2  v/  TO.Q2   ==>  '140/99'


NOTES:  

1.  There is not much error-checking for valid inputs in these 
    routines.  Perhaps an internal RPL version could do this without
    slowing down execution much (Joe?).

2.  Storing to and recalling 'denom' are subject to all the rules of
    the directory structure: "You can RCL from anyplace, but you STO
    where you sit."  That is, you can use (recall) 'denom' if it's in 
    a parent directory, but if you create a new value for 'denom', 
    it's stored in the current subdirectory. 

3.  I've assigned Joe's main program to the ->Q position on my 48,
    and TO.Q2 to the ->NUM position, so both are readily available.


4.  Again, all credit for DEC2FRAC (or TO.Q) goes to Joe Horn.

Following TO.Q2, I've listed Joe's program, in case you missed it.

%%HP: T(3)A(D)F(.);
@
@ TO.Q2 -- Calling program for TO.Q  (or DEC2FRAC, by Joe Horn)
@
@ Input:   2: real number to be converted to a fraction
@          1: list containing maximum denominator
@      or
@          1: real number to be converted to a fraction
@             (using previous maximum denominator)
@
\<< DUP TYPE
  IF 5 ==                 @ Does level 1 contain a list?
  THEN OBJ\-> DROP        @ If so, then extract the max denom and
'denom' STO               @ STOre it 
  END denom               @ Recall max denom to level 1
 TO.Q                     @ Dump to TO.Q -- change this to DEC2FRAC
\>>                       @   if you use the original name

Note:  My first version of TO.Q2 used a binary value rather than a 
list in level 1 to specify a new max denom.  But -- my 48 is 
usually in HEX mode -- I often forgot to add the 'd' to the binary.
If you prefer using a binary value, change:
     5    to    10
     OBJ\->  DROP   to   B\->R


Stephen J Thomas
sjthomas@cup.portal.com
akcs.sjthomas@hpcvbbs.uucp


%%HP: T(3)A(D)F(.);
@ TO.Q  (or DEC2FRAC)  by Joseph K. Horn
\<< DUP2
  IF 1 > SWAP FP
AND
  THEN \-> f c
    \<< 0 1 f
      WHILE OVER c
< OVER AND
      REPEAT INV
DUP FP 4 ROLLD IP
OVER * ROT + ROT
      END DROP DUP2
c
      IF DUP2 >
      THEN - OVER /
CEIL * -
      ELSE 3 DROPN
      END DUP2 1 2
      START DUP f *
0 RND SWAP / f -
ABS SWAP
      NEXT
      IF >
      THEN SWAP
      END DROP DUP
f * 0 RND SWAP
    \>>
    IF DUP ABS 1 >
    THEN # 5603Eh
SYSEVAL
    ELSE DROP
    END
  ELSE DROP
  END
\>>

wscott@en.ecn.purdue.edu (Wayne H Scott) (03/27/91)

In article <40605@cup.portal.com> sjthomas@cup.portal.com (Stephen J Thomas) writes:
>
>*** HP 48SX ***
>
>First, congratulations to Joe Horn for his recently posted algorithm


I was also impressed with Mr Horns's new program.  (I assigned it to ->Q's
old spot on the keyboard) 

I think two things should be added to the program but I don't know how
to do one of them.

It would be nice if:

2: { .25 .5 .75 }
1: 10				<-- I can do this one.
DEC2FRAC
1: { '1/4' '1/2' '3/4' }


2: '.5*X-.75'
1: 10
DEC2FRAC			<-- ->Q works this way but I don't know how
1: '1/2*X-3/4'			   to duplicate it.

Someone who understands the HP should disassemble ->Q and find out how
it parses equations and put the same functionality into DEC2FRAC.
Maybe even rewrite it is assembly.
-- 
_________________________________________________________________________
Wayne Scott             |  INTERNET: wscott@ecn.purdue.edu
Electrical Engineering  |  BITNET:   wscott%ecn.purdue.edu@purccvm
Purdue University       |  UUCP:     {purdue, pur-ee}!ecn.purdue.edu!wscott

bson@rice-chex.ai.mit.edu (Jan Brittenson) (03/28/91)

In a posting of [27 Mar 91 12:55:28 GMT]
   wscott@en.ecn.purdue.edu (Wayne H Scott) writes:

 > 2: '.5*X-.75'
 > 1: 10
 > DEC2FRAC			<-- ->Q works this way but I don't know how
 > 1: '1/2*X-3/4'			   to duplicate it.


   The following program used ->Q instead of DEC2FRAC (only for
illustrative purposes, I don't have DEC2FRAC at hand):

DO->Q:

<< IFERR OBJ-> 			@ Break up algebraic
   -> n oper			@ Save operand count and operator (e.g. +)
     << 1 n START		@ Loop operands
	  DO->Q			@ Convert operand
	  n ROLL		@ Move to next operand circularly
	NEXT
	oper EVAL		@ Join back together
     >>
   THEN ->Q END			@ Not algebraic - apply your ->Q here
>>


Thus, '(.5+.2)/.1' DO->Q results in '(1/2+1/5)/(1/10)'

   Limitations are of course arguments made up of lists, programs,
strings, etc, that are acceptable to OBJ->. The IFERR construct can be
replaced by a rather extensive type check, much easier done with
system RPL. I didn't keep Joe's DEC2FRAC (assuming I can get it from
your server whenever I need it), but the code above should be fairly
trivial to adapt to it. (So we'll leave that as a reader exercise.)

						-- Jan Brittenson
						   bson@ai.mit.edu

akcs.joehorn@hpcvbbs.UUCP (Joseph K. Horn) (03/29/91)

Wayne Scott asks for DEC2FRAC to parse equations like ->Q does.

No problem.  I'm on it...

-- Joe Horn --

wscott@en.ecn.purdue.edu (Wayne H Scott) (03/31/91)

In article <27f2c9cd:1772.4comp.sys.handhelds;1
>Wayne Scott asks for DEC2FRAC to parse equations like ->Q does.
>
>No problem.  I'm on it...
>
>-- Joe Horn --

Sorry I've already done it...

This program handles:
	real numbers
	complex numbers
	equations
	TAGGED objects
	lists
	and any combination of the above

{ .25 '.5*X-.75' (.25, -.333) }
10
DO\->Q
{ '1/4' '1/2*X-3/4' '1/4-1/3*i' }


I now have this programs assigned to my old \->Q key.
Many thanks to:
	Joseph Korn for writing the DEC2FRAC program
and	Jan Brittenson for showing me how to handle equations.
		(I never knew OBJ\-> would do that)

[ sorry typed in by hand }
DO\->Q
Checksum: # C215h
Size:	386

\<< \-> A D
\<< A TYPE \-> T \<<
  CASE T 0 ==
	THEN A D D2F END
	T 9 == THEN A OBJ\-> \-> n oper \<<
	1 n START D DO\->Q n ROLL NEXT
	oper EVAL \>>
	END
	T 1 == THEN A RE D DO\->Q A IM D DO\->Q i * + END
	T 5 == THEN A OBJ\-> \-> n \<< 1 n 
	START D DO\->Q n ROLL NEXT
	n \->LIST \>>
	END
	T 12 == THEN
	A OBJ\-> SWAP D DO\->Q SWAP \->TAG END
	A
  END
\>> \>> \>>

	
D2F is the same program posted eariler with the following changes.

D2F
Checksum: # 2667h
Size: 339
%%HP:T(3);
\<< DUP2 
  IF 1 > SWAP FP AND 
  THEN SWAP EVAL \-> c f	@ added EVAL so it can handle '2/4'
    \<< 0 1 f 
      WHILE OVER c < OVER AND 
      REPEAT INV DUP FP 4 ROLLD IP OVER * ROT + ROT 
      END DROP DUP2 c 
      IF DUP2 > 
      THEN - OVER / CEIL * - 
      ELSE 3 DROPN 
      END DUP2 1 2 
      START DUP f * 0 RND SWAP / f - ABS SWAP 
      NEXT 
      IF > 
      THEN SWAP 
      END DROP DUP f * 0 RND  
    \>> 
IF OVER 0 < THEN NEG SWAP NEG ELSE SWAP END	@ so -.25 -> -(1/4) not 1/-4
    IF DUP ABS 1 > 
    THEN # 5603Eh SYSEVAL 
    ELSE DROP 
    END 
  ELSE DROP 
  END 
\>>

Joe --  Is there a better way to handle negitive fractions?


-- 
_________________________________________________________________________
Wayne Scott             |  INTERNET: wscott@ecn.purdue.edu
Electrical Engineering  |  BITNET:   wscott%ecn.purdue.edu@purccvm
Purdue University       |  UUCP:     {purdue, pur-ee}!ecn.purdue.edu!wscott

bson@rice-chex.ai.mit.edu (Jan Brittenson) (03/31/91)

In a posting of [30 Mar 91 19:10:31 GMT]
   wscott@en.ecn.purdue.edu (Wayne H Scott) writes:

 > This program handles:
 >	real numbers
 >	complex numbers
 >	equations
 >	TAGGED objects
 >	lists
 >	and any combination of the above

So all we have to do now, is:

	1. Rewrite Wayne's and Joe's programs in system RPL.

	2. Write +, -, INV, SIN, etc, functions to
	   replace the keyboard equivalents. Basically, they
	   should check to see whether one of their arguments
	   is an algebraic - if not, just chain to the standard
	   function. Otherwise, we apply the standard operator,
	   EVAL, and DO->Q.

	3. Appropriate system flag -54, conveniently among
	   the "Display Format Flags" to mean "fractional
	   display." If the flag isn't set, just do the
	   standard old thing, regardless of arguments.

	4. Write a vectored ENTER function to automatically
	   DO->Q on all input, if flag -54 is set, otherwise
	   it should do nothing.

	5. Get the "maximum denominator" parameter from a
	   'FRACpar' variable instead of the stack.

	6. Add code to handle fractional units imposed by the
	   brain damage of the English unit system - Joe's
	   wish list seems like a good starting point.

	7. Package it all in a library.

   Voila' - we have an exceptionally useful fractional library.
Perhaps the most useful one ever put in a calculator? I think just
using a "display format" is the way to go, rather than trying to
implement fractions symbolically.

						-- Jan Brittenson
						   bson@ai.mit.edu

cloos@acsu.buffalo.edu (James H. Cloos) (04/01/91)

In article <14476@life.ai.mit.edu> bson@rice-chex.ai.mit.edu (Jan Brittenson) writes:
|In a posting of [30 Mar 91 19:10:31 GMT]
|   wscott@en.ecn.purdue.edu (Wayne H Scott) writes:
|
| > This program handles:
| >	real numbers
| >	complex numbers
| >	equations
| >	TAGGED objects
| >	lists
| >	and any combination of the above
|
|So all we have to do now, is:
|
|	1. Rewrite Wayne's and Joe's programs in system RPL.
|
|	2. Write +, -, INV, SIN, etc, functions to
|	   replace the keyboard equivalents. Basically, they
|	   should check to see whether one of their arguments
|	   is an algebraic - if not, just chain to the standard
|	   function. Otherwise, we apply the standard operator,
|	   EVAL, and DO->Q.
|
|	3. Appropriate system flag -54, conveniently among
|	   the "Display Format Flags" to mean "fractional
|	   display." If the flag isn't set, just do the
|	   standard old thing, regardless of arguments.
|
|	4. Write a vectored ENTER function to automatically
|	   DO->Q on all input, if flag -54 is set, otherwise
|	   it should do nothing.
|
|	5. Get the "maximum denominator" parameter from a
|	   'FRACpar' variable instead of the stack.
|
|	6. Add code to handle fractional units imposed by the
|	   brain damage of the English unit system - Joe's
|	   wish list seems like a good starting point.
|
|	7. Package it all in a library.
|
|   Voila' - we have an exceptionally useful fractional library.
|Perhaps the most useful one ever put in a calculator? I think just
|using a "display format" is the way to go, rather than trying to
|implement fractions symbolically.
|
|						-- Jan Brittenson
|						   bson@ai.mit.edu

Thanks Jan.  I couldn't have said it better myself!

-JimC
--
James H. Cloos, Jr.		Phone:  +1 716 673-1250
cloos@ACSU.Buffalo.EDU		Snail:  PersonalZipCode:  14048-0772, USA
cloos@ub.UUCP			Quote:  <>

sjthomas@cup.portal.com (Stephen J Thomas) (04/01/91)

In HP48 Insights Vol I, Bill Wickes presents a program which uses
vectored ENTER to provide fraction calculation capabilities for the 48.
It calls the built-in function ->Q.  Perhaps this could be incorporated
in the fraction package currently under development (Joe H., et al ?????).
I'd list it here, but it is copyrighted....so buy the book!!
  
Stephen J Thomas
sjthomas@cup.portal.com