[comp.sys.hp] Fraction Calculations on the HP-28C

gil@orstcs.CS.ORST.EDU (Gil Bachelor) (02/19/88)

	       Fraction Calculations on the HP-28C
	       -----------------------------------
    Hewlett-Packard's HP-28C Calculator is a remarkable machine;
HP has included most of the commonly used kinds of "objects" and
arithmetics on them.  However, there is one commonly used kind
of arithmetic which was left out.  I am referring to rational,
or fractional arithmetic.  Examples:  1/3 + 2/5 = 11/15;
(2/3) * (9/8) = 3/4.  Many of Casio's scientific calculators
have this capability.  I thought it would be handy if the HP-28C
could do this, too.
    It would take a rather large and complicated program to
evaluate an expression involving fractions and reduce the result
to lowest terms.  The HP-28C already has the ability to represent
and evaluate expressions (the so-called "algebraics").  All we 
need is the ability to convert the real, decimal result into a
fraction.  There was an article titled (approximately)
"Programming Insight: 0.8660254 = sqrt(3)/2", by Dan Sandberg,
published in BYTE Magazine 10, 5 (May 1985), pages 429-430.
This article describes "An algorithm that converts decimals to
fractions".  I have translated the program in "Listing 2" from
BASIC to HP-28C language, and modified it somewhat.  I have
tried to figure out how this algorithm works.  It seems to be 
related to Euclid's algorithm for finding the greatest common 
divisor of two integers.  However, this algorithm finds the 
denominator of the fraction represented by a decimal number.
    For convenience in editing, etc., I have divided the program
into a main program FRAC and a subroutine FLUP, which is called
from only one place in FRAC.  If desired, the code for FLUP can
be substituted into FRAC in place of the call on FLUP.  FRAC
(with the help of FLUP) attempts to convert a real number to a
fraction.  It will succeed in doing this if the real number is
sufficiently "close" to a fraction whose numerator and denominator
are "small" integers.  It appears that FRAC can handle any
non-zero fraction whose numerator and denominator are 3-digit 
integers or less.  It fails for some fractions involving 4-digit
integers.  What happens when it fails is that it loops, getting 
larger and larger numbers until overflow occurs, or (more 
probably) the user presses the ON button to stop it.  For example,
given the decimal number 3.14159292, it produces the fraction
'355/113'.  (This fraction gives a fairly close approximation to
pi).  When given the decimal number 3.14159265, it loops and fails
to produce an answer.  Thus, in a sense, it distinguishes between
"rational" and "irrational" numbers.
    Here is a listing of the program FRAC and the subroutine FLUP.
Some of the HP-28C characters do not exist in the ASCII character
set, and I have used substitutions below.  The program brackets
are represented by << and >>; the right arrow is -> (used in the
STR conversions); and <= represents "less than or equal to".
Note that the program uses variables A, B, and C.  It could
probably be re-written to make more use of the stack, and reduce
or eliminate the use of variables, but it seems easier to use
variables than to use stack manipulations.

FRAC: <<  EVAL  'A'  STO  A  ABS
      'C'  STO  1  'B'  STO
      FLUP  B  IP  'B'  STO
      "'"  A  B  *  .5  +  FLOOR
      ->STR  +  "/"  +  B  ->STR
      +  STR->  >>

FLUP: <<  DO  'B'  C  STO/  C
      INV  FP  'C'  STO  UNTIL
      C  .0001  <=  END  >>

    To use this program, enter FRAC and FLUP and store them under
these names.  Switch to the USER menu where FRAC is displayed.
When FRAC is executed, it takes one argument from the stack, which
must be a real number or an algebraic that EVAL's to a real number.
If FRAC succeeds, it returns one result to the stack, which is a
fraction in algebraic form.  Some examples:
(Both "Input" and "Output" are in position 1 of the stack)
        Input            Output
    -------------       ---------
     .33		'33/100'
     .333333		'1/3'
     .4375		'7/16'
     '1/3+2/5'		'11/15'
     'INV(11/15)'	'15/11'
     'FP(15/11)'	'4/11'
     '7/16+4/11'	'141/176'
     '33/100+1/3'	'199/300'
     '33/100*(1/3)'	'11/100'
     '33/100/(1/3)'	'99/100'

Note that the result is a fraction in algebraic form.  To convert
it to decimal form, simply press EVAL.  To convert it back to 
fraction form, execute FRAC.  A result, in either fractional or 
decimal form, can be used in further calculations, and the result
can be converted to fractional form (provided it satisfies the
limitations discussed above).  Of course, arithmetic operations
+ - * / applied to fractional operands produce fractional results.
Also, the functions 1/x, square, FP, and IP (and probably some
others) produce fractional results when applied to fractional
operands.

------------------------------------------------------------------
Gilbert A. Bachelor      | Internet: gil@cs.orst.edu
Dept. of Computer Science|     UUCP: {hp-pcd,tektronix}!orstcs!gil
Oregon State University  |
Corvallis, OR  97331     | Phone:  (503) 754-3273