(12C) Decimal to Fraction
|
08-08-2018, 10:26 PM
Post: #21
|
|||
|
|||
RE: (12C) Decimal to Fraction
(08-08-2018 06:05 PM)Thomas Klemm Wrote: Hi, Thomas I noticed some issues with above Python code. dec2frac(2.0, 10) crashes with ZeroDivisionError. "if c < 2 and" should be "if c < 2 or" -> since it is translated from calculator code, you might want to check this. Although not a bug in Python, when code running in a calculator, v can be huge. -> v might be much bigger than c, corrected v below c might be off. Below is the patched code: Code: def dec2frac(f, c): |
|||
08-09-2018, 12:11 AM
Post: #22
|
|||
|
|||
RE: (12C) Decimal to Fraction
(08-08-2018 10:26 PM)Albert Chan Wrote: dec2frac(2.0, 10) crashes with ZeroDivisionError. "if c < 2 and" should be "if c < 2 or" Nah, Joe is of course correct: Code: \<< DUP2 @ Must be two arguments. Exit now if max denominator < 2, It's only me that should study De Morgan's laws. Quote:Although not a bug in Python, when code running in a calculator, v can be huge. Not sure if I understand that correctly but that's something Joe might want to change in his RPL program as well. So this is rather a "jump forwards"? Thanks for the feedback Thomas |
|||
08-09-2018, 12:20 AM
Post: #23
|
|||
|
|||
RE: (12C) Decimal to Fraction | |||
08-09-2018, 12:51 AM
(This post was last modified: 08-09-2018 12:54 AM by Gamo.)
Post: #24
|
|||
|
|||
RE: (12C) Decimal to Fraction
This routine is to check for the FIX setting.
If 0.000 the result will show 3 This might be helpful to use in the decimal to fraction program. Code:
Gamo |
|||
08-09-2018, 01:57 AM
Post: #25
|
|||
|
|||
RE: (12C) Decimal to Fraction
This program for the HP-11C includes Dieter's and Albert's suggestions:
Code: *LBL A ; c f |
|||
08-09-2018, 02:17 AM
(This post was last modified: 08-09-2018 02:45 AM by Albert Chan.)
Post: #26
|
|||
|
|||
RE: (12C) Decimal to Fraction
Hi Thomas,
I was in the middle of typing this, when I see you fixed the code. Anyway, below illustrated why I request the fix. Try 0.10322, approx. with fraction, denominator <= 1e8 Using Mathematica, Continued Fraction coefficient = [0,9,1,2,4,1,6,2,1,4,3] With HP-12C, due to rounding error, I get [0,9,1,2,4,1,6,2,1,4,2,1,64,1,4,3,1,74139, ...] -> original setup, last 2 quotients = 68773261, 5098833198335 -> the big quotient rounded down in HP-12C to 5098833198000 -> interpolated quotient = 5098833198000 - 74139 * 68773261 = 52401000 (HP-12C rounded) -> fraction = 5408831 / 52401000 = 0.103219996 The fraction is wrong. Even with bad continued fraction coefficients, value should be very close to 0.10322 This is what the patched version does to above: -> fraction = 5408837 / 52401056 = 0.1032200000 |
|||
08-09-2018, 07:46 AM
Post: #27
|
|||
|
|||
RE: (12C) Decimal to Fraction
(08-09-2018 12:51 AM)Gamo Wrote: This routine is to check for the FIX setting. I cannot see how this may be related to the topic of this thread, but anyway it's a nice little utility that you may post in a separate thread. The program calculates round(1/3) – 1/3. This is always negative, so there is no need for an ABS via ENTER × √x: a CHS will do. Or simply reverse the order: 1/3 – round(1/3) is always positive. I assume that after this usually the base-10-logarithm is calculated, which the 12C does not offer. But instead of dividing the natural log by ln 10 (which is slow) here any value between 2,193 and 2,436 may be used. For instance √5 = 2,236. This is faster than a log and saves one step. So here is an updated version. I added an ENTER at the start, just to be sure... Code: 01 ENTER FIX 4 [R/S] => 4,0000 Re. line 07/08: LN CHS may by a tiiiny bit faster. ;-) Dieter |
|||
08-09-2018, 08:09 AM
Post: #28
|
|||
|
|||
RE: (12C) Decimal to Fraction
(08-09-2018 02:17 AM)Albert Chan Wrote: Try 0.10322, approx. with fraction, denominator <= 1e8 That's why I think the algorithm should stop if the fraction matches the input. My 35s program returns 5161/50000. Dieter |
|||
08-09-2018, 09:16 AM
Post: #29
|
|||
|
|||
RE: (12C) Decimal to Fraction
0.10322 on HP Prime also returns 5161/50000
Gamo |
|||
08-09-2018, 09:27 AM
(This post was last modified: 08-09-2018 10:35 AM by Dieter.)
Post: #30
|
|||
|
|||
RE: (12C) Decimal to Fraction
(08-08-2018 10:26 PM)Albert Chan Wrote: Below is the patched code: I have transcoded this for the 35s. Let me add a few remarks: First I think that q can also be calculated via q = c – (c–u) mod v. Can you confirm this? Also I do not quite understand why earlier code (and Joe's as well) used the CEIL function while here it's the FLOOR (or INT) function. Thomas even calculated 1+INT() which in most cases is the same as CEIL... but not for integer arguments. Then I wonder how exactly this Python diff() command works. Its arguments here are just the decimal input and a denominator – but not the corresponding numerator. So how does this work in detail? For instance, what is the value for diff(pi, 106) and diff(pi, 113)? In a calculator implementation first the numerators for the two possible results (denominators v and q) are calculated and then the errors are compared. These errors are evaluated by abs(input – numerator/denominator). This may lead to inaccuracies due to digit cancellation. Think of the √2 example (577/408 vs. 816/577). Is there a better way to compare the two possible fractions? Finally the code currently rejects integer input (which would lead to a division by zero). But can't this be trapped? For instance by leaving the while-loop if f=0? Or simply return v=1 if F is an integer? Dieter |
|||
08-09-2018, 09:30 AM
(This post was last modified: 08-09-2018 06:44 PM by Thomas Klemm.)
Post: #31
|
|||
|
|||
RE: (12C) Decimal to Fraction
Maybe I missed something but is there a reason for not using Farey sequences?
Python Code: def farey(q, n): HP-11C Code: LBL A This should also be easier to convert for the HP-12C since no subroutines are used. However the decimal number \(q\) to transform must be \(0 < q < 1\). Example 0.10322 ENTER EEX 8 [A] Y: 5,161 X: 50,000 Cheers Thomas |
|||
08-09-2018, 09:42 AM
Post: #32
|
|||
|
|||
RE: (12C) Decimal to Fraction
(08-09-2018 09:27 AM)Dieter Wrote: Then I wonder how exactly this Python diff() command works. Its arguments here are just the decimal input and a denominator – but not the corresponding numerator. So how does this work in detail? I assume that this is just the same function that I used: Code: def diff(f, d): Quote:For instance, what is the value for diff(pi, 106) and diff(pi, 113)? >>> from math import pi >>> diff(pi, 106) 8.32196275291075e-05 >>> diff(pi, 113) 2.667641894049666e-07 HTH Thomas |
|||
08-09-2018, 10:30 AM
(This post was last modified: 08-09-2018 10:39 AM by Dieter.)
Post: #33
|
|||
|
|||
RE: (12C) Decimal to Fraction
(08-09-2018 09:30 AM)Thomas Klemm Wrote: Maybe I missed something but is there a reason for not using Farey sequences? This should be easy to handle (use 1/input if input>1 and swap numerator and denominator afterwards). But this also means that you define the largest possible numerator. #-) I tried this algorithm on the 12C. Here is what I got for pi, using 1/pi as the input: 3,141592653 [1/x] 500 => 113/355 (as expected) 3,141592653 [1/x] 600 => 113/355 (as expected) 3,141592653 [1/x] 700 => 219/688 (?!?) What's this? Dieter |
|||
08-09-2018, 11:13 AM
(This post was last modified: 08-09-2018 06:46 PM by Thomas Klemm.)
Post: #34
|
|||
|
|||
RE: (12C) Decimal to Fraction
(08-09-2018 10:30 AM)Dieter Wrote: What's this? Oh, I see. It's just that: \(\frac{113}{355} < \frac{1}{\pi} < \frac{219}{688}\) Thus we can't simply return \(e, f\): Code: if b+d > n: Instead we should check whether \(\frac{a}{b}\) or \(\frac{c}{d}\) is closer to \(\frac{1}{\pi}\). Here's the output of: a, b, c, d Code: >>> farey(1/pi, 1000) As we know \(\frac{113}{355}\) is closer for a long time. We have to wait until \(\frac{33215}{104348}\) to get closer: Code: >>> farey(1/pi, 200000) Sorry for the slip. Thomas |
|||
08-09-2018, 12:16 PM
Post: #35
|
|||
|
|||
RE: (12C) Decimal to Fraction
(08-09-2018 09:27 AM)Dieter Wrote: I think that q can also be calculated via q = c – (c-u) mod v. Can you confirm this? q = u + (c-u)//v * v = c - ((c-u) - (c-u)//v * v) = c - (c-u) mod v -- confirmed Quote:I do not quite understand why earlier code (and Joe's as well) used the CEIL function why here it's the FLOOR (or INT) function. Thomas code use ceiling because v were over-shoot passed c: q = v - k u <= c k u >= v - c k >= (v - c) / u k = ceiling((v-c) / u) -- to maximize q My patch, both u, v are below c: q = u + k v <= c k <= (c - u) / v k = (c - u) // v -- to maximize q Quote:Thomas even used 1+INT() which in most cases is the same as CEIL... but not for integer arguments. 1+INT() for ceiling is wrong A simple example is 0.00005, u, v = 1, 20000 Since u = 1, 1+INT() always over-shoot ceiling by 1 |
|||
08-09-2018, 12:46 PM
(This post was last modified: 08-09-2018 03:19 PM by Albert Chan.)
Post: #36
|
|||
|
|||
RE: (12C) Decimal to Fraction
(08-09-2018 09:30 AM)Thomas Klemm Wrote: Maybe I missed something but is there a reason for not using Farey sequences? Perhaps Continued Fraction route is faster (and less restriction) ? (08-09-2018 10:30 AM)Dieter Wrote: This should be easy to handle (use 1/input if input>1 and swap numerator and denominator afterwards). Is it better do let Farey sequence handle fraction of input ? Numerator can be easily fixed later. Probably not even need fixing, mixed fraction is a "feature" :-) |
|||
08-09-2018, 03:39 PM
(This post was last modified: 08-09-2018 04:49 PM by Albert Chan.)
Post: #37
|
|||
|
|||
RE: (12C) Decimal to Fraction
I removed \(0 < x < 1\) restriction of farey fraction.
Code: >>> farey(0.10322, 1e8) # fractions match, stop Code: def farey(x, limit=100): |
|||
08-09-2018, 06:38 PM
Post: #38
|
|||
|
|||
RE: (12C) Decimal to Fraction
(08-09-2018 03:39 PM)Albert Chan Wrote: I removed \(0 < x < 1\) restriction of farey fraction. Very nice! This is my attempt to translate your program for the HP-11C: Code: *LBL A Quote: That's not implemented yet. So I'm leaving this as an exercise for the dear reader. Kind regards Thomas |
|||
08-09-2018, 10:15 PM
Post: #39
|
|||
|
|||
RE: (12C) Decimal to Fraction
(08-09-2018 06:38 PM)Thomas Klemm Wrote:(08-09-2018 03:39 PM)Albert Chan Wrote: I removed \(0 < x < 1\) restriction of farey fraction. I had revised my Python code after your HP-11C translation. Now: 1. hi = lo + 1 instead of 1/0 (infinity), thus saved 1 iteration 2. Both abs() calls are removed For reference, this was how I removed the restriction (see Farey Pair): Continued Fractions without Tears |
|||
08-10-2018, 12:28 PM
(This post was last modified: 08-10-2018 12:47 PM by Dieter.)
Post: #40
|
|||
|
|||
RE: (12C) Decimal to Fraction
(08-09-2018 06:38 PM)Thomas Klemm Wrote: Very nice! This is my attempt to translate your program for the HP-11C: Service: here is a translation for the 12C. Not available tests have been substituted, nmax is stored in the n-register, so that R1 is free and R2...R7 can move down to R1...R6. The output order has been reversed so that the numerator is returned in X and the denominator in Y. Code: 01 STO 0 The max. denominator is set with the [n] key. Output: numerator [X↔Y] denominator. 99 [n] 3,141592654 [R/S] => 311 [X↔Y] 99 2 [√x] [R/S] => 140 [X↔Y] 99 1 [ex] [R/S] => 193 [X↔Y] 71 20 [n] 1 [ex] [R/S] => 49 [X↔Y] 18 700 [n] 2 [√x] [R/S] => 816 [X↔Y] 577 999 [n] 3,141592654 [R/S] => 355 [X↔Y] 113 Now I wonder how long all this takes on an original hardware 12C... ;-) Note: You may replace line 23 with an x=0? test. This yields an x≤y? x=0? combination, and since x is always > 0 at this point the result logically is the desired x>y? test. ;-) Dieter |
|||
« Next Oldest | Next Newest »
|
User(s) browsing this thread: 7 Guest(s)