Here's a program for the
HP-11C:
Code:
*LBL A
STO 1 ; c f
CLx ; 0 f
STO 2 ; u=0 f
R↓ ; f
STO 0 ; f
1 ; 1 f
STO 3 ; v=1 f
*LBL 0 ; while
RCL 1 ; c v f
x≤y ; c ≤ v ?
GTO 1 ; done
R↓ ; v f
R↓ ; f
x=0 ; f = 0 ?
GTO 1 ; done
1/x ; 1/f
FRAC ; f'=frac(1/f)
RCL 2 ; u f'
LSTx ; 1/f u f'
INT ; int(1/f) u f'
RCL 3 ; v int(1/f) u f'
STO 2 ; u'=v
× ; v*int(1/f) f'
+ ; u+v*int(1/f) f'
STO 3 ; v'=u+v*int(1/f) f'
GTO 0 ; while
*LBL 1 ; done
x=y ; c = v ?
GTO 2 ; no need to jump
- ; v-c
RCL 2 ; u v-c
÷ ; (v-c)/u
INT ; int((v-c)/u)
1 ; 1 int((v-c)/u)
+ ; ceil((v-c)/u)
RCL 2 ; u ceil((v-c)/u)
× ; u*ceil((v-c)/u)
STO - 3 ; v -= u*ceil((v-c)/u)
*LBL 2 ; skip back
RCL 2 ; u
GSB 5 ; diff
RCL 3 ; v
GSB 5 ; diff
x≤y
GTO 3
RCL 2 ; u
GTO 4
*LBL 3
RCL 3 ; v
*LBL 4
ENTER ; q q
GSB 6 ; p q
RTN
*LBL 5 ; diff
ENTER ; d d
GSB 6 ; n d
x<>y ; d n
÷ ; n/d
RCL 0 ; f n/d
- ; n/d-f
ABS ; |n/d-f|
RTN ; diff
*LBL 6 ; round
RCL 0 ; f d
× ; f*d
. ;
5 ; 0.5 f*d
+ ; f*d+0.5
INT ; round(f*d)
RTN
It's the translation of this
Python program:
Code:
from math import modf, ceil
def diff(f, d):
n = round(d * f, 0)
return abs(f - n / d)
def dec2frac(f, c):
if c < 2 and int(f) == f:
return
u, v, F = 0, 1, f
while v < c and f:
g = 1 / f
f, _ = modf(g)
u, v = v, u + v * int(g)
if v > c:
v -= u * ceil((v - c) / u)
q = u if diff(F, u) < diff(F, v) else v
p = round(q * F, 0)
return p, q
Which is based on Joe Horn's
RPL program:
Code:
%%HP:T(3);
@ DEC2FRAC, by Joseph K. Horn
\<< DUP2 @ Must be two arguments. Exit now if max denominator < 2,
IF 1 > SWAP FP AND @ or if decimal fraction is an integer.
THEN \-> f c @ Store decimal fraction, and max denominator.
\<< 0 1 f @ Calculate only denominators. Do numerator only at end.
WHILE OVER c < OVER AND @ Do until bigger than max denominator
REPEAT INV DUP FP 4 ROLLD IP OVER * ROT + ROT @ This is the
END DROP DUP2 c @ recursion formula continued fraction expansion.
IF DUP2 > @ Is there a possible "missing" fraction?
THEN - OVER / CEIL * - @ This is the new, fast "jump backwards".
ELSE 3 DROPN @ (Sometimes there's no need to jump.)
END DUP2 1 2 @ Take the new denominator & the previous one, and
START DUP f * 0 RND SWAP / f - ABS SWAP @ turn into fractions.
NEXT @ See which one's closest to the original decimal fraction.
IF > @ Compare the two solutions, and
THEN SWAP @ pick the better one.
END DROP DUP f * 0 RND SWAP @ Calculate the numerator.
\>> @ End of real work; now clean up the output.
IF DUP ABS 1 > @ Is the denominator greater than 1?
THEN -3 CF # 5603Eh SYSEVAL @ If so, make output into 'A/B' form.
ELSE DROP @ Otherwise, get rid of extraneous denominator,
END @ and exit program.
ELSE DROP @ If bad arguments, do nothing to "decimal fraction", but
END @ get rid of "maximum denominator" and exit program.
\>>
You may have noticed that I skipped the initial test. But adding that is probably trivial.
Also I assume that this program can be easily adapted for the
HP-12C and other models.
Examples
1 ex 20 [A]
49
x<>Y
18
÷
2.7222
π 100 [A]
311
x<>y
99
÷
3.1414
Kind regards
Thomas
For those interested I've added the raw translation of the
Python program using the
Python to FOCAL Compiler:
Code:
LBL "DEC2FRA"
STO 01 ; c
RDN
STO 00 ; f
RDN
RCL 01 ; c
2
X<=Y?
GTO 00
RCL 00 ; f
INT
RCL 00 ; f
X#Y?
GTO 00
RTN
LBL 00
0
1
RCL 00 ; f
None
X<>Y
STO 02 ; u
RDN
STO 03 ; v
RDN
STO 04 ; F
RDN
LBL 01
RCL 03 ; v
RCL 01 ; c
X<=Y?
GTO 02
RCL 00 ; f
0
X=Y?
GTO 02
1
RCL 00 ; f
/
STO 05 ; g
RDN
RCL 05 ; g
None
STO 00 ; f
RDN
STO 06 ; _
RDN
RCL 03 ; v
RCL 02 ; u
RCL 03 ; v
RCL 05 ; g
INT
*
+
X<>Y
STO 02 ; u
RDN
STO 03 ; v
RDN
GTO 01
LBL 02
LBL 03
RCL 03 ; v
RCL 01 ; c
X>=Y?
GTO 04
RCL 03 ; v
RCL 02 ; u
RCL 03 ; v
RCL 01 ; c
-
RCL 02 ; u
/
XEQ CEIL
*
-
STO 03 ; v
RDN
GTO 04
LBL 04
RCL 04 ; F
RCL 02 ; u
XEQ DIST
RCL 04 ; F
RCL 03 ; v
XEQ DIST
X<=Y?
GTO 05
RCL 02 ; u
GTO 06
LBL 05
RCL 03 ; v
LBL 06
STO 07 ; q
RDN
RCL 07 ; q
RCL 04 ; F
*
0
RND
STO 08 ; p
RDN
RCL 08 ; p
RCL 07 ; q
RTN
This doesn't work but it gave me a skeleton which was helpful to start with.