(02-02-2016 09:35 PM)quantalume Wrote: Wow, this is really nice! I have not been able to find any errors in testing. I did make one small change. So as not to display the sign twice for negative output expressed as mixed numbers (this is just a personal preference), I replaced lines 50 and 51 with:
Code:
50 FC? 05
51 GTO 06
52 FS? 01
53 CHS
54 LBL 06
Logically this tests if both flag flag 05 and flag 01 are set. This can be accomplished without labels in a composite test, the last one returning "always false":
Code:
FS? 05
FC? 01
FS? 54
CHS
BUT... this messes up the stack output. The idea behind the double sign was that the value of the rounded fraction should equal T + Z/Y, and this is returned in X. Try it for negative input, and you'll see it doesn't work.
I think the following version works better and the result should be displayed the way you prefer. It's even one line shorter.
Code:
01 LBL"D2F"
02 RCL d
03 X<>Y ' Save status register on stack
04 CF 05
05 X<0?
06 SF 05 ' Set sign flag
07 ABS
08 RCL 00 ' A simple constant like 32 or 64 can be used here as well
09 STO 02 ' Store denominator in R02
10 *
11 FIX 0
12 CF 29
13 RND
14 STO 01 ' Store nominator in R01
15 FS? 02 ' Constant denominator mode?
16 GTO 02 ' Then skip GCD calculation
17 RCL 02
18 LBL 01 ' Use Euclidean algorithm
19 MOD ' to compute gcd(R01, R02)
20 LASTX
21 X<>Y
22 X≠0?
23 GTO 01
24 + ' = GCD
25 ST/ 01 ' reduce fraction
26 ST/ 02
27 LBL 02
28 CLX ' Set integer part "a" = 0
29 FS? 01 ' Improper fraction mode?
30 GTO 03 ' Then skip conversion to mixed number
31 RDN
32 RCL 01
33 RCL 02
34 MOD ' compute "b" = nominator mod denominator
35 X<> 01 ' and store it in R01
36 RCL 02
37 /
38 INT ' compute "a" = nominator DIV denominator
39 LBL 03 ' Start of formatting routine for result "a b/c"
40 " " ' Here "a" is in X while "b" and "c" are in R01 and R02
41 FS? 05 ' Start with a blank or minus sign
42 "-"
43 X=0? ' if a = 0
44 GTO 04 ' do not display it
45 ARCL X ' else append it
46 "├ "
47 FS? 05 ' adjust sign of integer part a
48 CHS
49 LBL 04
50 RCL 01
51 FS? 05 ' adjust sign of nominator b
52 CHS
53 X=0? ' if nominator = 0
54 GTO 05 ' skip adding b/c
55 ARCL 01 ' else append unsigned nominator,
56 "├/" ' append fraction bar
57 ARCL 02 ' and denominator
58 LBL 05 ' At this point the output line is complete
59 STO 01 ' Store sign-adjusted nominator
60 RCL 02 ' Calculate a + b/c
61 ST/ 01 ' R01 = b/c
62 R↑ ' Recall status bits from stack
63 STO d ' and restore original mode settings
64 RDN
65 RCL Z ' add integer part
66 ST+ 01 ' to R01
67 X<> 01 ' and move result = a + b/c to X
68 X=0? ' The (AFAIK) only case that's not handled properly
69 " 0" ' is x=0, so use a pragmatic solution. ;-)
70 AVIEW ' Display result
71 END ' Quit with a, b, c and a+b/c on the stack.
As usual: try it and see if it works for you. All error reports are welcome.
Dieter