How to simplify a fraction in Python? - python

still learning Python so any help is welcome.
I have written a funtion to get a fraction, but more often than not the fraction can be simplified. My code does not do this yet. Any ideas how to simplify the fraction without using any import functions?
code:
def add_frac(n1, d1, n2, d2):
frac = (((n1 * d1) + (n2 * d2)), (d1 * d2))
return frac
example:
add_frac(1, 2, 1, 4) gives (6, 8) in stead of (3, 4)
Any help is welcome!

A pretty naive approach to get you started, you can add some checks to make it more efficient.
def simplify_frac(n, d):
i = 2
while i < min(n, d) + 1:
if n % i == 0 and d % i == 0:
n = n // i
d = d // i
else:
i += 1
return n, d
# Some examples
In [105]: simplify_frac(2, 4)
Out[105]: (1, 2)
In [106]: simplify_frac(16, 36)
Out[106]: (4, 9)
In [107]: simplify_frac(7, 3)
Out[107]: (7, 3)
In [108]: simplify_frac(10, 1)
Out[108]: (10, 1)
In [109]: simplify_frac(1, 10)
Out[109]: (1, 10)
In [110]: simplify_frac(102, 10)
Out[110]: (51, 5)
In [111]: simplify_frac(110, 10)
Out[111]: (11, 1)
We use a modulo operator % to check the remainder from integer division by i, if both n and d have a remainder of 0 we know i divides them.

In addition to above answers, if you cannot import any other libraries, here's is the implementation of fractions.gcd for python 2.7 (copied from https://stackoverflow.com/a/11175154/10155740)
>>> print inspect.getsource(gcd)
def gcd(a, b):
"""Calculate the Greatest Common Divisor of a and b.
Unless b==0, the result will have the same sign as b (so that when
b is divided by it, the result comes out positive).
"""
while b:
a, b = b, a%b
return a
so if you'd incorporate this in your code, you should get something like:
def gcd(a, b):
while b:
a, b = b, a%b
return a
def add_frac(n1, d1, n2, d2):
frac = (((n1 * d1) + (n2 * d2)), (d1 * d2))
return tuple(i//gcd(*frac) for i in frac)
print(add_frac(1,2,1,4))
# OUTPUT: (3, 4)

The naive form of adding two fractions returns a correct answer, just not the most reduced correct answer. For that, you need to divide the numerator and denominator of the result by the greatest common denominator (GCD) of the original denominators. In this case, the GCD of 2 and 4 is 2, so dividing 6 and 8 by 2 gives the desired answer (3,4)
math.gcd can be used:
from math import gcd
def add_frac(n1, d1, n2, d2):
x = gcd(d1, d2)
frac = (((n1 * d2) + (n2 * d1)) / x, (d1 * d2) / x)
return frac
though it sounds like you are expected to define your own implementation of gcd.

Here is a solution with a recursive implementation of gcd, using Euclid Algorithm; it also works on negative numbers :
def mygcd(a, b) :
return gcd_rec(abs(a), abs(b))
def gcd_rec(a,b) :
if a*b == 0 : return a+b
if a <= b : return gcd_rec(a, b % a)
return gcd_rec(a % b, b)
def add_frac(n1, d1, n2, d2):
n = n1*d2 + n2*d1
d = d1*d2
g = mygcd(n, d)
return n//g, d//g

You need to divide it by GCD.
import math
def add_frac(n1, d1, n2, d2):
nume = (n1 * d1) + (n2 * d2)
deno = d1 * d2
gcd = math.gcd(nume,deno)
nume /= gcd
deno /= gcd
return (nume,deno)
>>> add_frac(1,2,1,4)
>>> (3.0, 4.0)

Related

How to determine the arrangement of the polynomial when displaying it with latex?

I am not sure if it is an issue with my python code or with the latex but it keeps rearranging my equation in the output.
Code:
ddx = '\\frac{{d}}{{dx}}'
f = (a * x ** m) + (b * x ** n) + d
df = sym.diff(f)
df_string = tools.polytex(df)
f_string = tools.polytex(f)
question_stem = f"Find $_\\displaystyle {ddx}\\left({f_string}\\right)$_"
output:
In this case a = 9, b = -4, c = 4, m = (-1/2), n = 3 and I want the output to be in the order of the variable f.
I have tried changing the order to 'lex' and that did not work nor did .expand() or mode = equation
There is an order option for the StrPrinter. If you set the order to 'none' and then pass an unevaluated Add to _print_Add you can get the desired result.
>>> from sympy.abc import a,b,c,x,m,n
>>> from sympy import S
>>> oargs = Tuple(a * x ** m, b * x ** n, c) # in desired order
>>> r = {a: 9, b: -4, c: 4, m: -S.Half, n: 3}
>>> add = Add(*oargs.subs(r).args, evaluate=False) # arg order unchanged
>>> StrPrinter({'order':'none'})._print_Add(add)
9/sqrt(x) - 4*x**3 + 4
Probably this will not be possible in general, as SymPy expressions get reordered with every manipulation, and even with just converting the expression to the internal format.
Here is some code that might work for your specific situation:
from sympy import *
from functools import reduce
a, b, c, m, n, x = symbols("a b c m n x")
f = (a * x ** m) + (b * x ** n) + c
a = 9
b = -4
c = 4
m = -Integer(1)/2
n = 3
repls = ('a', latex(a)), ('+ b', latex(b) if b < 0 else "+"+latex(b)), \
('+ c', latex(c) if c < 0 else "+"+latex(c)), ('m', latex(m)), ('n', latex(n))
f_tex = reduce(lambda a, kv: a.replace(*kv), repls, latex(f))
# only now the values of the variables are filled into f, to be used in further manipulations
f = (a * x ** m) + (b * x ** n) + c
which leaves the following in f_tex:
9 x^{- \frac{1}{2}} -4 x^{3} 4

Naive Recursive Algorithm for Polynomial Multiplication in Python

I am trying to implement the divide-and-conquer algorithm for polynomial multiplication. Here is the pseudocode given in the lecture notes:
where A, B are lists of coefficients of each polynomial, n is the size of the problem (degree - 1) and a_l, b_l are indices of the coefficients of interest.
Here is my attempt at implementing it using Python3:
def poly_mult_dc_naive(A, B, n, a, b):
n = int(n)
a = int(a)
b = int(b)
C = [None] * int(2*n - 1)
if n == 1:
C[0] = A[a] * B[b]
return C[0]
C[0:n-1] = poly_mult_dc_naive(A, B, n//2, a, b)
C[n:2*n-1] = poly_mult_dc_naive(A, B, n//2, a + (n // 2), b + (n // 2))
W = poly_mult_dc_naive(A, B, n/2, a, b + (n // 2))
V = poly_mult_dc_naive(A, B, n/2, a + n/2, b)
C[n // 2:n + (n // 2) - 1] += W + V
return C
However I'm getting strange results. For example let A = [1,2,3,4] B = [4,3,2,1] I get:
[4, None, 8, 3, 6, 12, None, 16, 9, 12, 2, None, 4, 1, 2, None, 8, 3, 4, None, None]
Correct answer is [4, 11, 20, 30, 20, 11, 4]
Could someone please point out where I've gone wrong and how it could be done?
Quick update: I think I've managed to debug my code my using a numpy array for C instead of a list. Here is the updated version:
import numpy as np
def poly_mult_dc_naive(A, B, n: int, a: int, b: int):
C = np.zeros(2*n - 1, dtype=int) # here I changed it from list to np array
if n == 1:
C[0] = A[a] * B[b]
return C[0]
C[0:n-1] = poly_mult_dc_naive(A, B, n//2, a, b)
C[n:2*n-1] = poly_mult_dc_naive(A, B, n//2, a + (n // 2), b + (n // 2))
W = poly_mult_dc_naive(A, B, n//2, a, b + (n // 2))
V = poly_mult_dc_naive(A, B, n/2, a + (n//2), b)
C[(n // 2) : (3*n // 2) - 1] += W + V
return C
BONUS QUESTION: Does anyone know of a better way I could keep the arguments n, a, and b as int types?
I just feel like having to write:
n = int(n)
a = int(a)
b = int(b)
might not be the most elegant way.
There should be no need to coerce n,a,b from float to int. Just use // 2 integer division everywhere (i.e. in the W,V lines). That will "keep" ints as ints.
The line C[n // 2:n + (n // 2) - 1] badly needs parenthesizing, it misreads very easily. I'd write C[(n//2) : (3*n//2)-1]
But I seriously recommend you use numpy vectors, not Python lists. Adding, multiplying etc. are vectorized.

Python - How to write a program to get the remainder of the quotient of two numbers without using %, //, / or any multiplication?

I'm really stuck on this. I could do it with integer division and multiplication but I have no idea how to find the remainder without any of these operators. (can't import anything either. the main premise is to use while loops).
>>> def solution(a, b):
... while a >= b:
... a -= b
... return a
...
>>> solution(11, 5) == (11 % 5)
True
>>> solution(763, 47) == (763 % 47)
True
Just an efficient one:
def mod(a, b):
if a >= b:
a = mod(a, b + b)
if a < b:
return a
return a - b
Demo:
>>> a, b = 75349157395712349036170927572349157024, 543791534729045
>>> mod(a, b)
510757213184524
>>> a % b
510757213184524

Solving linear equation with large numbers

I have equation of form a+b*n1=c+d*n2, where a,b,c,d are known numbers with around 1000 digits and I need to solve n1.
I tried:
i=1
while True:
a=(a+b)%d
if(a==c):
break
i+=1
print(i)
, but this method is too slow for numbers this big. Is there some better method to use in this kind of situations?
You want to find x such that x = a (mod b) and x = c (mod d). For then, n1 = (x - a) / b and n2 = (x - c) / d.
If b and d are coprime, then the existence of x is guaranteed by the Chinese Remainder Theorem -- and a solution can be found using the Extended Euclidean Algorithm.
If b and d aren't coprime (that is, if gcd(b, d) != 1), then (noting that a = c (mod gcd(b, d))), we can subtract a % gcd(b, d) from both sides, and divide through by gcd(b, d) to reduce to a problem as above.
Putting it into code
Here's code that finds n1 and n2 using this method:
def egcd(a, b):
if a == 0:
return (b, 0, 1)
else:
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)
def modinv(a, m):
return egcd(a, m)[1] % m
def solve(a, b, c, d):
gcd = egcd(b, d)[0]
if gcd != 1:
if a % gcd != c % gcd:
raise ValueError('no solution')
a, c = a - a % gcd, c - c % gcd
a //= gcd
b //= gcd
c //= gcd
d //= gcd
x = a * d * modinv(d, b) + c * b * modinv(b, d)
return (x - a) // b, (x - c) // d
And here's some test code that runs 1000 random trials of 1000-digit inputs:
import sys
sys.setrecursionlimit(10000)
import random
digit = '0123456789'
def rn(k):
return int(''.join(random.choice(digit) for _ in xrange(k)), 10)
k = 1000
for _ in xrange(1000):
a, b, c, d, = rn(k), rn(k), rn(k), rn(k)
print a, b, c, d
try:
n1, n2 = solve(a, b, c, d)
except ValueError, exn:
print 'no solution'
print
continue
if a + b * n1 != c + d * n2:
raise AssertionError('failed!')
print 'found solution:', n1, n2
print
(Note, the recursion limit has to be increased because the egcd function which implements the Extended Euclidean algorithm is recursive, and running it on 1000 digit numbers can require a quite deep stack).
Also note, that this checks the result when a solution is returned. But when a != c (mod gcd(b, d)) and the exception is raised signalling no result, no check is done. So you need to think through if this can fail to find results when solutions do exist.
This runs (1000 trials) in around 7-8 seconds on my machine, so it performs reasonably well.

Modular multiplicative inverse function in Python

Does some standard Python module contain a function to compute modular multiplicative inverse of a number, i.e. a number y = invmod(x, p) such that x*y == 1 (mod p)? Google doesn't seem to give any good hints on this.
Of course, one can come up with home-brewed 10-liner of extended Euclidean algorithm, but why reinvent the wheel.
For example, Java's BigInteger has modInverse method. Doesn't Python have something similar?
Python 3.8+
y = pow(x, -1, p)
Python 3.7 and earlier
Maybe someone will find this useful (from wikibooks):
def egcd(a, b):
if a == 0:
return (b, 0, 1)
else:
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)
def modinv(a, m):
g, x, y = egcd(a, m)
if g != 1:
raise Exception('modular inverse does not exist')
else:
return x % m
If your modulus is prime (you call it p) then you may simply compute:
y = x**(p-2) mod p # Pseudocode
Or in Python proper:
y = pow(x, p-2, p)
Here is someone who has implemented some number theory capabilities in Python: http://www.math.umbc.edu/~campbell/Computers/Python/numbthy.html
Here is an example done at the prompt:
m = 1000000007
x = 1234567
y = pow(x,m-2,m)
y
989145189L
x*y
1221166008548163L
x*y % m
1L
You might also want to look at the gmpy module. It is an interface between Python and the GMP multiple-precision library. gmpy provides an invert function that does exactly what you need:
>>> import gmpy
>>> gmpy.invert(1234567, 1000000007)
mpz(989145189)
Updated answer
As noted by #hyh , the gmpy.invert() returns 0 if the inverse does not exist. That matches the behavior of GMP's mpz_invert() function. gmpy.divm(a, b, m) provides a general solution to a=bx (mod m).
>>> gmpy.divm(1, 1234567, 1000000007)
mpz(989145189)
>>> gmpy.divm(1, 0, 5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: not invertible
>>> gmpy.divm(1, 4, 8)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: not invertible
>>> gmpy.divm(1, 4, 9)
mpz(7)
divm() will return a solution when gcd(b,m) == 1 and raises an exception when the multiplicative inverse does not exist.
Disclaimer: I'm the current maintainer of the gmpy library.
Updated answer 2
gmpy2 now properly raises an exception when the inverse does not exists:
>>> import gmpy2
>>> gmpy2.invert(0,5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: invert() no inverse exists
As of 3.8 pythons pow() function can take a modulus and a negative integer. See here. Their case for how to use it is
>>> pow(38, -1, 97)
23
>>> 23 * 38 % 97 == 1
True
Here is a one-liner for CodeFights; it is one of the shortest solutions:
MMI = lambda A, n,s=1,t=0,N=0: (n < 2 and t%N or MMI(n, A%n, t, s-A//n*t, N or n),-1)[n<1]
It will return -1 if A has no multiplicative inverse in n.
Usage:
MMI(23, 99) # returns 56
MMI(18, 24) # return -1
The solution uses the Extended Euclidean Algorithm.
Sympy, a python module for symbolic mathematics, has a built-in modular inverse function if you don't want to implement your own (or if you're using Sympy already):
from sympy import mod_inverse
mod_inverse(11, 35) # returns 16
mod_inverse(15, 35) # raises ValueError: 'inverse of 15 (mod 35) does not exist'
This doesn't seem to be documented on the Sympy website, but here's the docstring: Sympy mod_inverse docstring on Github
Here is a concise 1-liner that does it, without using any external libraries.
# Given 0<a<b, returns the unique c such that 0<c<b and a*c == gcd(a,b) (mod b).
# In particular, if a,b are relatively prime, returns the inverse of a modulo b.
def invmod(a,b): return 0 if a==0 else 1 if b%a==0 else b - invmod(b%a,a)*b//a
Note that this is really just egcd, streamlined to return only the single coefficient of interest.
I try different solutions from this thread and in the end I use this one:
def egcd(a, b):
lastremainder, remainder = abs(a), abs(b)
x, lastx, y, lasty = 0, 1, 1, 0
while remainder:
lastremainder, (quotient, remainder) = remainder, divmod(lastremainder, remainder)
x, lastx = lastx - quotient*x, x
y, lasty = lasty - quotient*y, y
return lastremainder, lastx * (-1 if a < 0 else 1), lasty * (-1 if b < 0 else 1)
def modinv(a, m):
g, x, y = self.egcd(a, m)
if g != 1:
raise ValueError('modinv for {} does not exist'.format(a))
return x % m
Modular_inverse in Python
Here is my code, it might be sloppy but it seems to work for me anyway.
# a is the number you want the inverse for
# b is the modulus
def mod_inverse(a, b):
r = -1
B = b
A = a
eq_set = []
full_set = []
mod_set = []
#euclid's algorithm
while r!=1 and r!=0:
r = b%a
q = b//a
eq_set = [r, b, a, q*-1]
b = a
a = r
full_set.append(eq_set)
for i in range(0, 4):
mod_set.append(full_set[-1][i])
mod_set.insert(2, 1)
counter = 0
#extended euclid's algorithm
for i in range(1, len(full_set)):
if counter%2 == 0:
mod_set[2] = full_set[-1*(i+1)][3]*mod_set[4]+mod_set[2]
mod_set[3] = full_set[-1*(i+1)][1]
elif counter%2 != 0:
mod_set[4] = full_set[-1*(i+1)][3]*mod_set[2]+mod_set[4]
mod_set[1] = full_set[-1*(i+1)][1]
counter += 1
if mod_set[3] == B:
return mod_set[2]%B
return mod_set[4]%B
The code above will not run in python3 and is less efficient compared to the GCD variants. However, this code is very transparent. It triggered me to create a more compact version:
def imod(a, n):
c = 1
while (c % a > 0):
c += n
return c // a
from the cpython implementation source code:
def invmod(a, n):
b, c = 1, 0
while n:
q, r = divmod(a, n)
a, b, c, n = n, c, b - q*c, r
# at this point a is the gcd of the original inputs
if a == 1:
return b
raise ValueError("Not invertible")
according to the comment above this code, it can return small negative values, so you could potentially check if negative and add n when negative before returning b.
To figure out the modular multiplicative inverse I recommend using the Extended Euclidean Algorithm like this:
def multiplicative_inverse(a, b):
origA = a
X = 0
prevX = 1
Y = 1
prevY = 0
while b != 0:
temp = b
quotient = a/b
b = a%b
a = temp
temp = X
a = prevX - quotient * X
prevX = temp
temp = Y
Y = prevY - quotient * Y
prevY = temp
return origA + prevY
Well, here's a function in C which you can easily convert to python. In the below c function extended euclidian algorithm is used to calculate inverse mod.
int imod(int a,int n){
int c,i=1;
while(1){
c = n * i + 1;
if(c%a==0){
c = c/a;
break;
}
i++;
}
return c;}
Translates to Python Function
def imod(a,n):
i=1
while True:
c = n * i + 1;
if(c%a==0):
c = c/a
break;
i = i+1
return c
Reference to the above C function is taken from the following link C program to find Modular Multiplicative Inverse of two Relatively Prime Numbers

Categories

Resources