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