From gil@orstcs.cs.orst.edu.UUCP Thu Feb 18 15:11:56 1988
Path: gmu90x!pyrdc!uunet!seismo!sundc!pitstop!sun!amdcad!ames!rutgers!orstcs!gil
From: gil@orstcs.CS.ORST.EDU (Gil Bachelor)
Newsgroups: comp.sys.handhelds,comp.sys.hp
Subject: Fraction Calculations on the HP-28C
Message-ID: <2771@orstcs.CS.ORST.EDU>
Date: 18 Feb 88 20:11:56 GMT
Reply-To: gil@orstcs.cs.orst.edu.UUCP (Gil Bachelor)
Organization: Oregon State University - CS - Corvallis, Oregon
Lines: 101


	       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




Path: gmu90x!pyrdc!uunet!tank!nic.MR.NET!hal!cwjcc!mailrus!cornell!vax5!jhc
From: jhc@vax5.CIT.CORNELL.EDU
Newsgroups: comp.sys.handhelds
Subject: HP-28 notes, icl. program
Message-ID: <17253@vax5.CIT.CORNELL.EDU>
Date: 5 Nov 88 04:04:37 GMT
Sender: news@vax5.CIT.CORNELL.EDU
Reply-To: jhc@vax5.cit.cornell.edu ()
Distribution: comp
Organization: Cornell Computer Services, Cornell University, Ithaca, NY 14853


Somebody (sorry, can't find the reference in the files I ftp'ed from the
archive) posted a couple of programs, FRAC and FLUP, that take a decimal
and return a fraction in the form 'numerator/denominator'.  As posted
it used non-local variables for intermediate storage.  I rewrote it to use
only local variables as I don't like cluttering my directories (too much)
and found that it speeded the routine up considerably.  It's listed below
under the name FRAC.  Also listed is a hack to reduce a decimal to the
form 'integer+numerator/denominator' for when the improper form is a no-go.
It calls FRAC on the FP portion of the input.  O->S is from 411, and is
listed below for those of you who don't have that.  (It converts an object
into a string, getting rid of the ''s in the case of names, &c.)  S->N is
also c/o Tom Affinito and converts a string into a name.

FRAC
<<	EVAL DUP ABS 1 SWAP -> a b c
	<<
		DO b c / 'b' STO c INV FP 'c' STO
		UNTIL c .00001 <=
		END a b IP
	>>	-> a b
	<<	"'" a b * .5 + FLOOR ->STR + "/" + b ->STR + STR->
	>>
>>

O->S  (c/o Thomas Affinito)
<<	->STR DUP SIZE 1 - 2 SWAP SUB
>>

S->N  (c/o Thomas Affinito)
<< "'" SWAP + STR->
>>

The following is saved under MYFRAC on my 28S.  I can't think of a good
name for it.  It is the one that gives output like '3+4/5' for 3.8
<<	-> a
	<<	a IP ->NUM ->STR
		IF a ->NUM FP
		THEN "+" + a FP FRAC O->S +
		END S->N
	>>
>>

I'm sure that this last one could be dressed up a bit, but as I said it is
just a temp hack.  Can anyone think of a good name for the final version
of it?

BTW, FRAC will still loop continuously if you try to do 3.14159265359 FRAC
or try it with other irrationals.

If you missed the orriginal posting, try things like '3+3/8+7/16' FRAC to
get a hang of how it works.  The output of FRAC EVALuates to the decimal.

These routines can be generalized to work w/ arrays, complex numbers, &c.
Actually all you need is things like IFERR ARRY-> THEN ELSE DROP to get
the valuse into reals, do FRAC from 1 to DEPTH, and then reconstruct the
array.  Hmmm, can't have algebraics in an array, oh well, you'd have to
settle for {}'s rather than []'s in the array and use it for display
purposes only.  Of course complex numbers can be represented as
'(num1/denom1)+(num2/denom2)*i' which will EVAL into a format useable
in calculations.  I may work on it if I get the time.

Thats all for now, folks.

-JimC
--
James H. Cloos, Jr.          "Entropy isn't what it used to be."
jhc@Crnlvax5.BITNET            --c/o Fortune @ batcomputer.UUCP
jhc@Vax5.CCS.Cornell.ED		 #include <std_disclaimers.h>
cornell!vax1!vax5.ccs.cornell.edu!jhc@rochester.UUCP
B-7 Upson Hall, Cornell Univ., Ithaca, NY 14853   +1 607 272 4519
From jurjen@cwi.nl Sat Nov 19 09:49:35 1988
Path: gmu90x!pyrdc!jetson!uunet!mcvax!jurjen
From: jurjen@cwi.nl (Jurjen N.E. Bos)
Newsgroups: comp.sys.handhelds
Subject: Improvement on the FRAC function
Summary: You give the number of accurate digits
Message-ID: <7720@boring.cwi.nl>
Date: 19 Nov 88 14:49:35 GMT
Organization: CWI, Amsterdam



Now about my FRAC function.  The advantage over the previous version is that
it works on ALL numbers in the range 1e-10 to 1e10, and that it gives you
a fraction that matches to a specified number of digits.  It will give you,
with input pi and accuracy 5 digits, the famous approximation 355/113.
Input:
2: real number, range 1e-10 .. 1e10
1: real number, specifying the number of accurate digits after the point
Output:
2: numerator
1: denominator

Program:
<< NEG ALOG .5 * 1 0 -> X P A B
   << X WHILE
   'ABS(FLOOR(X*A+.5)-X*A)>=P*A'
   EVAL REPEAT
   INV DUP IP ABS A * B +
   A 'B' STO 'A' STO FP END
   DROP 'FLOOR(X*A+.5)' EVAL A >> >>

Poor me... I can't afford a 28S!

-- 
  -- Jurjen N.E. Bos (jurjen@cwi.nl)


