Exemplo n.º 1
0
def harmonic_series():
    out = Rational(1)
    ctr = 2
    while True:
        yield out
        out += Rational(1, ctr)
        ctr += 1
Exemplo n.º 2
0
def liouville_convergents(b=10):
    k = 1
    out = Rational(0)
    ctr = 1
    while True:
        out += Rational(1, b**k)
        ctr += 1
        k *= ctr
        yield out
Exemplo n.º 3
0
def farey_sequence(n):
    """All unique fractions between 0 and 1 with denominator less than or equal to n"""
    a, b, c, d = 0, 1, 1, n
    yield Rational(0)

    while c <= n:
        k = (n + b) // d
        a, b, c, d = c, d, k * c - a, k * d - b
        yield Rational(a, b)
Exemplo n.º 4
0
def question_mark_func(n):
    """Use the Farey sequences to calculate the question mark function"""

    known_val = {Rational(0): Rational(0), Rational(1): Rational(1)}

    out = [(Rational(0), Rational(0))]
    for i in range(1, n):

        S = farey_sequence(i)

        a = next(S)
        b = next(S)
        while True:
            new = mediant(a, b)
            val = (known_val[a] + known_val[b]) / 2

            if new not in known_val:
                known_val[new] = val
                out.append((new, val))

            a = b
            try:
                b = next(S)
            except StopIteration:
                break

    out += [(Rational(1), Rational(1))]
    out = sort_by_nth(out, 0)
    return out
Exemplo n.º 5
0
def bernoulli_numbers(n):
    B = 0
    for k in range(n + 1):
        for v in range(k + 1):
            B += (-1)**v * choose(k, v) * Rational(v**n, k + 1)

    return B
Exemplo n.º 6
0
def rational_round(Q,dlim):
    """Best approximation of Q with denominator of d or less, by semi-convergents"""

    Q = cast_to_rational(Q)
    if type(dlim) != int:
        raise TypeError("dlim must be integer")
    if dlim < 1:
        raise ZeroDivisionError

    # https://shreevatsa.wordpress.com/2011/01/10/not-all-best-rational-approximations-are-the-convergents-of-the-continued-fraction/
    a = CFrac(Q).terms

    prev = Rational(a[0])
    for pos,val in enumerate(a):
        # Try appending the floor of half the next convergent
        semi = a[:pos]+[(val-1)//2+1]
        semi = CFrac(semi)
        
        # If it is worse than the last semiconvergent add 1
        if abs(semi.as_rational() - Q)  >  abs(prev - Q):
            semi[pos] += 1
            
        while semi.terms[pos] <= val:
            if semi.as_rational().d > dlim:
                semi[pos] -= 1
                return prev
            prev = semi.as_rational()
            semi[pos] += 1
    return Q
Exemplo n.º 7
0
def all_pos_rationals():
    """Generate all positive rational numbers"""
    yield Rational(0)
    diag = 1
    prev = set()
    while True:
        N = 1
        D = diag
        for i in range(diag):
            r = Rational(N,D)
            if r not in prev:
                prev.add(r)
                yield r
            N += 1
            D -= 1
        diag += 1
Exemplo n.º 8
0
def cast_to_rational(T):
    """Best effort to transform input to a rational number"""

    if type(T) == Rational:
        return T

    elif type(T) == int:
        return Rational(T)

    elif type(T) == float:
        return cast_to_rational(str(T))

    elif type(T) == CFrac:
        return T.as_rational()

    elif type(T) == str:
        for func in [
                ratio_to_frac, int_str_to_frac, term_dec_to_frac,
                rep_dec_to_frac, scientific_to_frac
        ]:
            out = func(T)
            if type(out) == Rational:
                return out
        raise ValueError(f"Could not cast {T} to Rational")

    else:
        raise ValueError(f"Could not cast {T} to Rational")
Exemplo n.º 9
0
def rep_dec_to_frac(S):
    """Convert a string representing a repeating decimal to Rational"""

    m = re.fullmatch("-?\d*\.\d*\(\d+\)", S)
    is_neg = 1
    if m:

        if S[0] == "-":
            is_neg = -1
            S = S[1:]

        T = re.sub("\(|\)|\.", "", S)

        D = first_where(S, ".") - 1  # pos of decimal
        R = first_where(S, "(") - 2  # pos of repeating part

        A = int(T)
        B = int(T[:R + 1])

        mul_full = 10**(len(T) - 1)
        mul_rep = 10**R
        mul_dec = 10**D

        return Rational(A - B, (mul_full - mul_rep)) * mul_dec * is_neg

    else:
        return None
Exemplo n.º 10
0
def int_str_to_frac(S):
    """Convert a string representing an integer to Rational"""
    m = re.fullmatch("-?\d+", S)
    if m:
        return Rational(int(S))
    else:
        return None
Exemplo n.º 11
0
def harmonic_progression(a=1, d=1):

    a = cast_to_rational(a)
    d = cast_to_rational(d)

    den = a
    one = Rational(1)
    while True:
        yield one / den
        den += d
Exemplo n.º 12
0
    def convergents(self):
        """Rational convergents"""

        A1 = self.terms[0]
        A2 = self.terms[1] * self.terms[0] + 1

        B1 = 1
        B2 = self.terms[1]

        yield Rational(A1, B1)

        for d in self.terms[2:]:

            A1, A2 = A2, d * A2 + A1
            B1, B2 = B2, d * B2 + B1

            yield Rational(A1, B1)

        yield Rational(A2, B2)
Exemplo n.º 13
0
    def convergents(self):
        """Rational convergents"""

        A1 = self.dens[0]
        A2 = self.dens[1]*self.dens[0]+self.nums[0]
        
        B1 = 1
        B2 = self.dens[1]
        
        
        yield Rational(A1,B1)
        
        for d,n in zip(self.dens[2:],self.nums[1:]):
            
            A1, A2 = A2, d*A2+n*A1
            B1, B2 = B2, d*B2+n*B1
        
            yield Rational(A1,B1)
            
        yield Rational(A2,B2)
Exemplo n.º 14
0
def ratio_to_frac(S):
    """Convert a string of form a/b to Rational"""

    m = re.fullmatch("-?\d+\/\d+", S)
    is_neg = 1
    if m:
        if m[0] == "-":
            is_neg = -1
            m = m[1:]
        n, d = S.split("/")
        return Rational(int(n) * is_neg, int(d))
    else:
        return None
Exemplo n.º 15
0
def scientific_to_frac(S):
    """Convert a string formatted as e notation to Rational"""
    S = re.sub("e|⏨|\*\^", "E", S)
    m = re.fullmatch("-?\d\.\d+E-?\d+", S)

    if m:
        L, R = S.split("E")

        significand = term_dec_to_frac(L)
        power = Rational(10)**int(R)

        return significand * power
    else:
        return None
Exemplo n.º 16
0
def term_dec_to_frac(S):
    """Convert a string representing a terminating decimal to Rational"""

    m = re.fullmatch("-?\d*\.\d*", S)
    is_neg = 1
    if m:
        if S[0] == "-":
            is_neg = -1
            S = S[1:]
        D = len(S) - first_where(S, ".") - 1
        S = S.replace(".", "")
        return Rational(int(S) * is_neg, 10**D)
    else:
        return None
Exemplo n.º 17
0
 def as_rational(self):
     """Convert a generalized continued fraction to a Rational"""
 
     A1 = self.dens[0]
     A2 = self.dens[1]*self.dens[0]+self.nums[0]
     
     B1 = 1
     B2 = self.dens[1]
             
     for d,n in zip(self.dens[2:],self.nums[1:]):
         
         A1, A2 = A2, d*A2+n*A1
         B1, B2 = B2, d*B2+n*B1
         
     return Rational(A2,B2) 
Exemplo n.º 18
0
    def as_rational(self):
        """Convert a continued fraction to a Rational"""

        L = self.terms

        N = [1, L[0]]
        D = [0, 1]
        con = 2

        while con < len(self) + 1:
            N.append(L[con - 1] * N[con - 1] + N[con - 2])
            D.append(L[con - 1] * D[con - 1] + D[con - 2])
            con += 1

        return Rational(N[-1], D[-1])
Exemplo n.º 19
0
    def semiconvergents(self):
        """Rational semiconvergents"""

        a = self.terms
        Q = self.as_rational()

        prev = Rational(a[0])
        for pos, val in enumerate(a):
            # Try appending the floor of half the next convergent
            semi = a[:pos] + [(val - 1) // 2 + 1]
            semi = CFrac(semi)

            # If it is worse than the last semiconvergent add 1
            if abs(semi.as_rational() - Q) > abs(prev - Q):
                semi.terms[pos] += 1

            while semi.terms[pos] <= val:
                yield prev
                prev = semi.as_rational()
                semi.terms[pos] += 1
        yield Q
Exemplo n.º 20
0
    while True:
        w, f = R.mixed_form()
        L.append(w)
        if f == 0:
            break
        R = f.inv()
    return L


if __name__ == '__main__':

    C = CFrac([8, 11, 4, 2, 7])
    print(C)
    print(C.pretty_name)

    print(CFrac(Rational(3, 4)))

    print()
    print(C)
    C += [1, 1]
    print(C)
    C.insert(3, 5)
    print(C)
    C[1] = 7
    print(C)
    C[2] += 9
    print(C)
    del C[6]
    print(C)

    D = CFrac([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
Exemplo n.º 21
0
    out = []
    
    while u != 0:
        a = (1/u).__ceil__()
        out.append(a)
        u = u*a-1
    return out
    




if __name__ == '__main__':
    
    print("GCD and LCM")
    a = Rational(13,6)
    b = Rational(3,4)
    G = rational_gcd(a,b)
    L = rational_lcm(a,b)
    print(f"gcd({a},{b}) = {G}")
    print(f"lcm({a},{b}) = {L}")
    
    
    print("\n\nRational Sequence")
    print(rational_seq(0,3,Rational(2,3)))
    
    
    print("\n\nRationalRound")
    R = Rational(214159,470)
    print(R)
    print(rational_round(R,100))
Exemplo n.º 22
0
def mediant(a,b):

    a = cast_to_rational(a)
    b = cast_to_rational(b)
    
    return Rational(a.n+b.n,a.d+b.d)
Exemplo n.º 23
0
def _rational_gcd(A,B):
    """Largest rational such that both A and B are integer multiples of it"""
    assert type(A) == Rational
    assert type(B) == Rational
    return Rational(gcd(A.n*B.d,A.d*B.n),(A.d*B.d))