g | x | w | all
Bytes Lang Time Link
212APLNARS251006T050639ZRosario
061Perl 5 p MListUtil=min200722T085321ZNahuel F
061Python 3200722T073112ZDavid Fo
060R200722T082345ZKirill L
075R200725T083134ZDominic
066Julia200724T151232ZFederico
169Python 3.8200722T140113ZAlexey B
060Wolfram Language Mathematica200722T135419ZZaMoC
087Python 2200721T164444ZiLikeTra
071Python 3.8 prerelease200722T001125ZSurculos
078Io200722T012212Zuser9206
026APL Dyalog Unicode200722T021500ZBubbler
031Charcoal200721T231940ZNeil
149Zig 0.6.0200721T205604Zpfg
015Japt v2.0a0 g200721T172344ZShaggy
011Jelly200721T183120ZJonathan
01105AB1E200721T164551ZKevin Cr

APL(NARS), 212 chars

h←{⍬≡r←⍸⍺≥÷1∨¨k←⌽+∘÷\⍵:⍬⋄1≥i←¯2+↑r:k[↑r]⋄2>≢r←i↓k:1↑r⋄2↑r}∘{∞≤∣⍵:⍬⋄m,∇÷⍵-m←⌊⍵}
v←{(i z)←(⌊,(1∘∣))÷/⍎¨⍕¨1∧¨⍵⋄w←({1∧⍵},{÷1∨⍵})⍵[2]⋄k/⍨⍺≥÷1∨¨k←⌽÷/¨{⍎(⍕⍵),'x'}¨¨{⌈w×⍵}¨1,z+0,⍳i}
p←{1≥≢m←⍺h⍵:m⋄m←⍺v m⋄m[↑⍸k=⌊/k←∣m-⍵]}

// +/79 95 38=212

the function 'p' has as input left [⍺] one positive integer (that would be the max denominator) and as input right [⍵] one rational type, and return zilde or a rational type.

It would use the continue fraction expansion of the input ⍵, get from the expansions the 'sum' more near to ⍵ that has denominator less than ⍺, and the 'sum' that follow that, the one more precise it is not matter if denominator is >⍺. For example

  1000000 h 3.14159265359x
5419351r1725033 1146408r364913 

From this 2 rational numbers find the division of the two numerators among them for obtain a decimal number, in example

  5419351 ÷ 1146408 
4.727244576

and use the fractional part of it (0.727244576) for find the number that seems to be the fraction that has min abs difference value from ⍵ with denominator ≤ ⍺.

Test:

  8 p 1.21x
6r5 
  1000000 p 3.14159265359x
3126535r995207 
  12 p 3.14159265359x
22r7 
  225 p 0.0748947977x  
14r187 
  1000000 p 19.0x
19 
  100 p 2.7182818x
193r71 
  22 p 0.8193927511x 
9r11 
  20 p 0.2557463559x 
1r4 
  100 p 0.2557463559x 
11r43 

The code it seems break for denominators > 100000000000x

  ⎕fpc←1024
  1024÷3.322
308.2480433
  80⍕○1v
3.14159265358979323846264338327950288419716939937510582097494459230781640628620900
  aa←3.14159265358979323846264338327950288419716939937510582097494459230781640628620900x
  10000000000x p aa
10886058930r3465140179 
  100000000000x p aa
10886058930r3465140179 
  1000000000000x p aa
597964296r190337947 
  10000000000000x p aa
5912477861r1882000155 
  90⍕∣10886058930r3465140179-aa
0.000000000001506760081764004719735822028917648541680158284026944442004048915485730336859483
  90⍕∣5912477861r1882000155-aa
0.000000000001515505297419494124190885830197957760107654303699020598498454609419685389130586

Note that 10886058930r3465140179 is a better approssimation of the 'aa' number than 5912477861r1882000155 and it should not be that.

Perl 5 -p -MList::Util=min, 65, 61 bytes

-4 bytes thanks to DomHastings

/ /;$_=min map abs($`-($-=.5+$_*$`)/$_)." $-/$_",1..$';s;.* ;

Try it online!

Python 3, 66 61 bytes

lambda x:Fraction(x).limit_denominator
from fractions import*

Try it online!

The above function takes a floating point number and returns a bound function Fraction.limit_denominator which, in turn, takes the upper bound for the denominator to return a simplified, approximated fraction as requested.

As you can tell, I’m more of an API reader than a golfer.


R, 61 60 bytes

With a byte saved by Dominic van Essen.

function(x,d,n=round(1:d*x))c(m<-order((x-n/1:d)^2)[1],n[m])

Try it online!

R, 75 bytes

function(x,d)c((n=rep(0:1,e=d)+(1:d*x)%/%1)[f<-order((x-n/1:d)^2)[1]],f%%d)

Try it online!

Not a competitive answer as it's already beaten by Kirill, but posting for fun anyway.

I didn't think of the round() function, so this approach rounds down & then up to generate a double-length list of candidate numerators, and then finds the index of the closest fraction. Since the index might be in the second (rounded-up) part of the list, the denominator is the index mod the length of the single-length list.

I think it's fair to conclude that the round() function indeed serves a useful role...

Julia, 66 bytes

r(x,m)=minimum((n=Int(round(x*d));(abs(x-n/d),n//d)) for d=1:m)[2]

or

(x,m)->minimum((n=Int(round(x*d));(abs(x-n/d),n//d)) for d=1:m)[2]

Python 3.8, 169 bytes

Maybe the reason why there was no submissions using Farey sequences is that the code appears rather lengthy.

In short, every proper fraction \$\frac{m}{k}\$ in lowest terms appears in Farey sequence of order \$d\$ if and only if \$k\le d\$.
Farey sequences are constructed by taking mediant of neighboring terms of lower order: \$\left(\frac ab,\frac cd\right)\to\frac{a+c}{b+d}\$, starting from \$\left(\frac 01,\frac 11\right)\$. And the target number is within one of the intervals \$\left[\frac ab,\frac{a+c}{b+d}\right]\$, \$\left[\frac{a+c}{b+d},\frac cd\right]\$, then we take the interval as a current one.

So the algorithm is:

  1. Take \$\left(\frac ab,\frac cd\right):=\left(\frac 01,\frac 11\right)\$.
  2. Take \$\frac{m}{k}:=\frac{a+c}{b+d}\$ and compare with target.
  3. If \$\frac{m}{k}>\$ target, replace \$\frac{a}{b}\$ by \$\frac{m}{k}\$,
  4. Else replace \$\frac{c}{d}\$ by \$\frac{m}{k}\$.
  5. If the next denominator \$b+d\$ is no more than denominator limit, repeat from 2.
  6. Else return nearest from \$\frac ab,\frac cd\$ to the target.
def f(e,n,g,j):
	if n==0:return e,1
	x=[(0,1),(1,1)]
	while True:
		(a,b),(c,d)=x
		if b+d>j:break
		m,k=a+c,b+d
		x[m*g>n*k]=(m,k)
	m,k=x[2*n/g-a/b>c/d]
	return m+e*k,k

Try it online!

Eats (entire_part,proper_numerator,proper_denominator,denominator_limit) and produces (numerator,denominator), like

>>> f(3,141592653589793,10**len('141592653589793'),57)
(179, 57)

P.S. Recursive version is nothing but shorter, even with all whitespace removed:

f=(lambda e,n,g,j,a=0,b=1,c=1,d=1:
   n and(
       b+d>j and(lambda x,y:(x+e*y,y))(*([(a,b),(c,d)][2*n/g-a/b>c/d]))
       or((m:=a+c)*g>n*(k:=b+d))and f(e,n,g,j,a,b,m,k)or f(e,n,g,j,m,k,c,d)
       )or(e,1)
   )

Try it online!

Wolfram Language (Mathematica), 60 bytes

(t=s=1;While[Denominator[s=Rationalize[#,1/t++]]<#2,j=s];j)&

Try it online!

Python 2, 168, 135, 87 bytes

z=i=1
def f(x,y):exec"r=round(x*i);q=abs(r/i-x)\nif q<z:z=q;t=r;u=i\ni+=1;"*y;print t,u

Try it online!

Thank you all for your recommendations on my first golf!

Python 3.8 (pre-release), 77 71 bytes

-6 bytes thanks to @ovs !

lambda x,n:min([abs(x-(a:=round(x*b))/b),a,b]for b in range(1,n+1))[1:]

Try it online!

Simply try all denominators from 1 to n, saving all results into a list where each element has the form [error, numerator, denominator]. By taking the min of the list, the fraction with the smallest error is selected.

Io, 78 bytes

Port of Surculose Sputum's answer.

method(x,y,Range 1to(y)map(a,list((x-(b :=(a*x)round)/a)abs,b,a))min slice(1))

Try it online!

Io, 93 bytes

method(x,y,list(((q :=(r :=Range 0to(y)map(a,(x-(a*x)round/a)abs))indexOf(r min))*x)round,q))

Try it online!

Explanation (ungolfed):

method(x, y,                   // Take two operands
    r := Range 0 to(y) map(a,  // Map in range 0..y (set to r):
        (x-(a*x)round/a)abs    //     |x-round(a*x)/a|
    )                          //     (Aka find the appropriate numerator)
    q :=r indexOf(r min)       // Set q as the 0-index of the smallest number of r
    list((q*x)round,q)         // Output [numerator,denominator]
)                              // End function

APL (Dyalog Unicode), 26 bytes

⌊.5+(⊃∘⍋1+|⍨⌊⊢-|⍨)∘÷∘⍳×1,⊣

Try it online!

A dyadic tacit function that takes the decimal number on its left and the max denominator on its right, and gives a 2-element vector of [denominator, numerator].

How it works

⌊.5+(⊃∘⍋1+|⍨⌊⊢-|⍨)∘÷∘⍳×1,⊣  ⍝ Left: x, Right: d
                  ∘÷∘⍳      ⍝ v←[1, 1/2, ..., 1/d]
    (          |⍨)          ⍝ Remainder of x divided by each of v
          |⍨⌊⊢-             ⍝ Min distance from x to some integer multiple of v
        1+                  ⍝ Add 1 to treat close enough numbers as same
                            ⍝ Otherwise it gives something like 5/20 due to FP error
     ⊃∘⍋                    ⍝ D←The index of minimum (the optimal denominator)
                      ×1,⊣  ⍝ Exact fraction (D,Dx)
⌊.5+                        ⍝ Round both

Charcoal, 31 bytes

Nθ⪫…⮌⌊EEN⌊⁺·⁵×θ⊕κ⟦↔⁻θ∕ι⊕κ⊕κι⟧²/

Try it online! Link is to verbose version of code. Explanation:

Nθ                              Input decimal as a number
        N                       Input maximum denominator
       E                        Map over implicit range
                κ               Current index (0-indexed)
               ⊕                Increment (i.e. 1-indexed)
             ×                  Multiplied by
              θ                 Input decimal
         ⌊⁺·⁵                   Round to nearest integer
      E                         Map over results
                      ι         Current numerator
                     ∕          Divided by
                       ⊕κ       Current denominator
                    θ           Input decimal
                  ↔⁻            Absolute difference
                         ⊕κ     Current denominator
                           ι    Current numerator
                 ⟦          ⟧   Make into list
     ⌊                          Take the minimum (absolute difference)
    ⮌                           Reverse the list
   …                         ²  Take the first two entries
  ⪫                           / Join with literal `/`
                                Implicitly print

I'm not 100% sure that the algorithm is correct, so just in case, here's a 34-byte brute-force solution:

NθFNF⊕⌈×θ⊕ι⊞υ⟦↔⁻θ∕κ⊕ι⊕ικ⟧I⊟⌊υ/I⊟⌊υ

Try it online! Link is to verbose version of code. Very slow, so test case is limited to a denominator of 1000. Explanation:

Nθ

Input the decimal.

FN

Loop over the possible denominators (except 0-indexed, so all of the references to the loop variable have to be incremented).

F⊕⌈×θ⊕ι

Loop until the nearest numerator above.

⊞υ⟦↔⁻θ∕κ⊕ι⊕ικ⟧

Save the fraction difference and the denominator and numerator.

I⊟⌊υ/I⊟⌊υ

Print the numerator and denominator of the fraction with the minimum difference.

Zig 0.6.0, 149 bytes

fn a(e:f64,m:f64)[2]f64{var n:f64=1;var d=n;var b=d;var c=b;while(d<m){if(n/d>e)d+=1 else n+=1;if(@fabs(n/d-e)<@fabs(b/c-e)){b=n;c=d;}}return.{b,c};}

Try it

Formatted:

fn a(e: f64, m: f64) [2]f64 {
    var n: f64 = 1;
    var d = n;
    var b = d;
    var c = b;
    while (d < m) {
        if (n / d > e) d += 1 else n += 1;
        if (@fabs(n / d - e) < @fabs(b / c - e)) {
            b = n;
            c = d;
        }
    }
    return .{ b, c };
}

Variable declarations are annoying.

Japt v2.0a0 -g, 15 bytes

mc ×õ ï ñ@ÎaXr÷

Try it

mc ×õ ï ñ@ÎaXr÷     :Implicit input of array U
m                   :Map
 c                  :  Ceiling
   ×                :Reduce by multiplication
    õ               :Range [1,result]
      ï             :Cartesian product with itself
        ñ           :Sort by
         @          :Passing each pair X through the following function
          Î         :  First element of U
           a        :  Absolute difference with
            Xr÷     :  X reduced by division
                    :Implicit output of first pair

Jelly, 11 bytes

Ċ×⁹p÷/ạ¥Þ⁸Ḣ

A dyadic Link accepting the decimal [evaluated as a float] on the left and the denominator limit on the right which yields a pair [numerator, denominator] representing the simplified fraction.

Try it online! Or see the test-suite (big denominator limit cases removed due to inefficiency.)

How?

Ċ×⁹p÷/ạ¥Þ⁸Ḣ - Link: v, d
Ċ           - ceil (of the decimal value, v)
 ×⁹         - multiplied by chain's right argument (denominator limit, d)
   p        - Cartesian power (d) -> all pairs [[1,1],...,[1,d],[2,1],...,[Ċ×⁹,d]]
                  (note that any pair representing a non-simplified fraction is to
                   the right of its simplified form)
        Þ   - (stable) sort by:
       ¥    -   last two links as a dyad:
     /      -     reduce by:
    ÷       -       division (i.e. evaluate the fraction)
      ạ  ⁸  -     absolute difference with the chain's left argument (v)
          Ḣ - head

05AB1E, 11 bytes

î*LãΣ`/¹α}н

Try it online or verify all test cases (except for the two 1000000 test cases, which take too long).

Explanation:

î          # Ceil the (implicit) input-decimal
 *         # Multiply it by the (implicit) input-integer
  L        # Pop and push a list in the range [1, ceil(decimal)*int]
   ã       # Create all possible pairs of this list by taking the cartesian product
    Σ      # Sort this list of pairs by:
     `     #  Pop and push both values separated to the stack
      /    #  Divide them by one another
       ¹α  #  Get the absolute difference with the first input-decimal
    }н     # After the sort: leave only the first pair
           # (after which it is output implicitly as result)