fraction between 2 number, minimum denominator
|
09-16-2023, 07:47 PM
Post: #1
|
|||
|
|||
fraction between 2 number, minimum denominator
From thread Companion program for Joe Horn’s continued fractions article.
Python code, translated for HP Prime (if micro-Python available, that should work too) Code: d_convergent(a,b, d1,d2) Once minimum denominator are picked, program pick minimum numerator too. Code assumed number are *exact* fractions, not float. Cas> frac_between(18/10,19/10) --> 9/5 Cas> frac_between(18/10,18/10) --> 9/5 Cas> frac_between(18/10,17/10) --> 7/4 Cas> frac_between(18/10,16/10) --> 5/3 Cas> frac_between(18/10,15/10) --> 3/2 Cas> frac_between(18/10,14/10) --> 3/2 Cas> frac_between(999999999977/10^12,999999999978/10^12) --> 43478260869/43478260870 |
|||
09-18-2023, 11:28 PM
Post: #2
|
|||
|
|||
RE: fraction between 2 number, minimum denominator
(09-16-2023 07:47 PM)Albert Chan Wrote: Cas> frac_between(18/10,18/10) --> 9/5 Cas> frac_between(1.8, 1.8) practically hang the emulator. Cas 48 bits float('1.8') = hexfloat(0x1.cccccccccccc) < 9/5 C:\> spigot -C 0x1.cccccccccccc 1/1 2/1 7/4 9/5 126663739519795/70368744177664 Because of rounding errors, d_convergent(1.8, 1.8, 1,0) only return [1,4], d nowhere close enough. The trick (for float) is to use mod: n/d = floor_div(n,d) + floor_mod(n,d)/d First term is CF coef, and we simply flip RHS fraction for others. If n≥0, d>0, (euclidean_mod = floor_mod = trunc_mod), and trunc_mod is *exact* see Eli Bendersky's blog, Computing remainders by doubling, recursive steps are exact. Unfortunately, Cas does not have mod for float. We use Lua to illustrate. Although we work with float, d convergents are exact. No fudge factor is needed. Code: function d_convergent(a,a2, b,b2, d,d2) -- 0 <= (a/a2) <= (b/b2) Code: function frac_between(a,b) -- assumed non-negative a,b lua> x = 0x1.cccccccccccc -- = Cas float("1.8") lua> d_convergent(x,1, x,1, 1,0) 5 70368744177659 lua> frac_between(x,x) -- = fraction(x) 126663739519795 70368744177664 lua> frac_between(0.999999999977, 0.999999999978) 43478173323 43478173324 Lua only see binary float, not decimal (*) In that sense, above fraction is correct. To reduce decimal to binary conversion error, instead of (a,b), lets do (1-a, 1-b) Note: numbers have 10 9's after decimal point. lua> frac_between(0.23E-10, 0.22E-10) 1 43478260870 Or, we enter (a,b), but input as actual fraction, to remove conversion error. lua> d_convergent(999999999977,1E12, 999999999978,1E12, 1,0) 1 43478260869 First d semi-convergent = 1 + 43478260869 = 43478260870 (*) I do have Decimal/Fraction version, lua + qmath C:\>run frac_between.lua 0.999999999977 0.999999999978 43478260869/43478260870 C:\>run frac_between.lua 10/7 13/9 10/7 |
|||
09-19-2023, 12:19 PM
(This post was last modified: 09-19-2023 05:07 PM by Albert Chan.)
Post: #3
|
|||
|
|||
RE: fraction between 2 number, minimum denominator
(09-18-2023 11:28 PM)Albert Chan Wrote: Lua only see binary float, not decimal (*) In that sense, above fraction is correct. If machine only see Decimal float, there is no bin↔dec conversion errors to worry about. Within machine precision limits, we could use fast float, instead of exact integers. Here is HP71B code, fraction = (numerator, denominator (default=1)). Quote:10 DESTROY ALL @ COMPLEX A,B Again, we assumed non-negative inputs. >run A, B= 1.8, 1.9 DCONV= 1 4 FRAC = (9,5) A, B= 1.8, 1.8 DCONV= 1 4 FRAC = (9,5) A, B= 1.8, 1.7 DCONV= 1 3 FRAC = (7,4) A, B= 1.8, 1.6 DCONV= 1 2 FRAC = (5,3) A, B= 1.8, 1.5 DCONV= 1 1 FRAC = (3,2) A, B= (10,7), (13,9) DCONV= 2 5 FRAC = (10,7) A, B= 3.1415, 3.1416 DCONV= 7 99 FRAC = (333,106) A, B= .999999999977, .999999999978 DCONV= 1 43478260869 FRAC = (43478260869,43478260870) Translated code for other decimal machine welcome ... |
|||
« Next Oldest | Next Newest »
|
User(s) browsing this thread: 2 Guest(s)