I'm currently writing a code to perform Gaussian elimination in MATLAB and then write out the code needed to generate a LaTex file showing all the steps. A lot of the times when I do Gaussian elimination the answers start turning into Fractions. So I thought as a nice learning exercise for classes in Matlab that I would write a Fraction class. But I have no clue how to overload operators and frankly Mathwork's documentation wasn't helpful.
classdef Fraction
properties
numer
denom
end
methods
function a = Fraction(numer,denom)
a.denom = denom;
a.numer = numer;
end
function r = mtimes(a,b)
r = Fraction(a.numer*b.numer,a.denom*b.demon);
end
function r = plus(a,b)
c = a.numer*b.denom+a.denom*b.numer;
d = a.denom*b.denom;
r = Fraction(c,d);
function r = minus(a,b)
c = a.numer*b.denom-a.denom*b.numer;
d = a.denom*b.denom;
r = Fraction(c,d);
end
function r = mrdivide(a,b)
r = Fraction(a.numer*b.denom,a.denom*b.numer);
end
function b = reduceFrac(a)
x = a.numer;
y = b.denom;
while y ~= 0
x = y;
y = mod(x,y);
end
b =Fraction(a.numer/x, a.denom/x)
end
end
end
The plus operator works but the other three do not. Does any one have any ideas? Also how do I call my method reduceFrac?
Fraction.reduceFrac(Fraction(2.4))
I thought that the code above would work, but it didn't. Below is the python version of what I am trying to acheive.
Fraction.py
class Fraction(object):
"""Fraction class
Attributes:
numer: the numerator of the fraction.
denom: the denominator of the fraction.
"""
def __init__(self, numer, denom):
"""Initializes the Fraction class
Sets the inital numer and denom for the
fraction class.
Args:
numer: Top number of the Fraction
denom: Bottom number of the Fraction
Returns:
None
Raises:
None
"""
self.numer = numer
self.denom = denom
def __str__(self):
"""function call along with the print command
Args:
None
Returns:
String: numer / denom.
Raises:
None
"""
return str(self.numer) + '/' + str(self.denom)
def get_numer(self):
return self.numer
def set_numer(self, numer):
self.numer = numer
def get_denom(self):
return self.denom
def set_denom(self, denom):
self.denom = denom
def __add__(self, other):
numer = self.numer*other.denom+other.numer*self.denom
denom = self.denom*other.denom
return Fraction.reduceFrac(Fraction(numer,denom))
def __div__(self, other):
numer = self.numer*other.denom
denom = self.denom*other.numer
return Fraction.reduceFrac(Fraction(numer,denom))
def __sub__(self, other):
numer = self.numer*other.denom-other.numer*self.denom
denom = self.denom*other.denom
return Fraction.reduceFrac(Fraction(numer,denom))
def __mul__(self, other):
numer = self.numer*other.numer
denom = self.denom*other.denom
return Fraction.reduceFrac(Fraction(numer,denom))
def reduceFrac(self):
x = self.numer
y = self.denom
while y != 0:
(x, y) = (y, x % y)
return Fraction(self.numer/x, self.denom/x)
if __name__ == "__main__":
v = Fraction(4,3)
g = Fraction(7,8)
r = Fraction(4,8)
a = v + g
print a
s = v - g
print s
d = v / g
print d
m = v * g
print m
f = Fraction.reduceFrac(r)
print f
Your plus function misses an end
Related
I was wondering if there is a way for a class to define a method that behaves like a static method (can be called without an instance variable) and a regular method (can be called with an instance variable).
Im making an RSA module that would help me solve RSA problems, the initialization goes like this:
class RSA:
def __init__(self, n: int, e: int, c: int, p=None, q=None, phi=None):
self.n = n
self.e = e
self.c = c
self.p = p
self.q = q
assert p == None or gmpy2.is_prime(p), 'p must be prime'
assert q == None or gmpy2.is_prime(q), 'q must be prime'
self.phi = phi
and in that class, there is a method that would factorize n into p and q which goes like this (the algorithm used is irrelevant so I wont bother explaining):
def fermat_factorization(self, n=None):
if n == None:
n = self.n
t_ = gmpy2.isqrt(n)+1
counter = 0
t = t_ + counter
temp = gmpy2.isqrt((t * t) - n)
while((temp * temp) != ((t * t) - n)):
counter += 1
t = t_ + counter
temp = gmpy2.isqrt((t * t) - n)
s = temp
p = t + s
q = t - s
return p, q
that implementation does not work. What I wanted to do is for that method to be dynamic, i.e. can be called externally by simply
p, q = RSA.fermat_factorization(n) # n is some large number
yet can also be called on an instance like:
s1 = RSA(n, 65537, c) # c and n is some large number
p, q = s1.fermat_factorization() # without specifying n because it is already an instance attribute
In python, you use modules for that kind of stuff, not classes:
in rsa.py
def fermat_factorization(n):
"""Ordinary function"""
class RSA:
def fermat_factorization(self):
"""Method"""
return fermat_factorization(self.n)
somewhere else:
import rsa
x = rsa.fermat_factorization(100)
obj = rsa.RSA(...)
y = obj.fermat_factorization()
Having a single function that behaves some way or another depending on how it's called is a recipe for disaster. Don't do that.
I am following the Runestone Academy Python3 course and tried to implement 'addition' feature for fractions using Class but I am getting error.
When I am not using GCD implementation, the code is running fine
Here is my code:
class Fraction:
def __init__(self, top, bottom):
self.num = top
self.den = bottom
def show(self):
print(f'{self.num}/{self.den}')
def __str__(self):
return f'{self.num}/{self.den}'
# adding without GCD implementation
# def __add__(self,other_fraction):
# new_num = self.num * other_fraction.den + self.den * other_fraction.num
# new_den = self.den * other_fraction.den
# return Fraction(new_num, new_den)
# adding with GCD implementation
def gcd(self, m, n):
while m % n != 0:
m, n = n, m % n
return n
def __add__(self, other_fraction):
new_num = self.num * other_fraction.den + self.den * other_fraction.num
new_den = self.den * other_fraction.den
common = gcd(new_num, new_den)
return Fraction(new_num // common, new_den // common)
# my attempt of adding two fractions by creating a method 'add'
# def add(self,other_fraction):
# new_num = self.num * other_fraction.den + self.den * other_fraction.num
# new_den = self.den * other_fraction.den
# return Fraction(new_num, new_den)
# my_fraction = Fraction(3,5)
# print(my_fraction)
# print(f'I ate {my_fraction} of my pizza')
# my_fraction.__str__()
# str(my_fraction)
f1 = Fraction(1, 4)
f2 = Fraction(1, 2)
f3 = f1 + f2
# f3 = f1.add(f2)
print(f3)
This is the error I am getting:
Traceback (most recent call last):
File "D:/Python/Mosh_Lec/app.py", line 74, in <module>
f3 = f1 + f2
File "D:/Python/Mosh_Lec/app.py", line 53, in __add__
common = gcd(new_num, new_den)
NameError: name 'gcd' is not defined
I also tried with this variation but same error:
def gcd(self, m, n):
self.num = m
self.den = n
while self.num % self.den != 0:
self.num, self.den = self.den, self.num % self.den
return self.den
The gcd method should not logically be part of the Fraction class. Indeed, you can call the gcd method with any two numbers, they do not need to be the numerator and denominator of a fraction. Therefore I would move the gcd function outside of the class.
def gcd(m, n):
...
class Fraction:
...
Look at there:
NameError: name 'gcd' is not defined
It means that it cannot find the function(or method) named gcd. Of course! It need to be called with a Fraction object, so try to change your source code at line 32:
- common = gcd(new_num, new_den)
+ common = self.gcd(new_num, new_den)
self is a Fraction object.
By the way, the method gcd that do not use the parament self should be defined as a static function:
class Fraction:
...
#staticmethod
def _gcd(m: int, n: int):
...
...
And call the method by Fraction._gcd (the underline means that it is private function(or method)).
See it's a simple issue if u see the error:
File "D:/Python/Mosh_Lec/app.py", line 53, in __add__
common = gcd(new_num, new_den)
NameError: name 'gcd' is not defined
you will see that you have defined gcd but why it is saying GCD, not defined here's the reason:
common = self.gcd(new_num, new_den)
It is as simple as that just put the above code like this:
def __add__(self, other_fraction):
new_num = self.num * other_fraction.den + self.den * other_fraction.num
new_den = self.den * other_fraction.den
common = self.gcd(new_num, new_den)
return Fraction(new_num // common, new_den // common)
and your problem is solved! Kudos!
It as simple as that.......
I'm trying to represent a matrix of complex numbers using 2 real value matrices (in Pytorch, but using numpy here just for illustrative purposes).
Currently I'm doing it this way:
import numpy as np
# represent real
X = np.random.randn(10,10)
# represent imaginary
I = np.random.randn(10,10)
# build complex matrix using the identity
real = np.concatenate([X, -I], axis=-1)
img = np.concatenate([I, X], axis=-1)
complex_W = np.concatenate([real, img,], axis=0)
# is complex_W now correctly represented??
Could I also do it this way?
# represent real
X = np.random.randn(10,10)
# represent imaginary
I = np.random.randn(10,10)
complex_W = X + I
You can implement complex ndarray data structure using numpy arrays. You may want to store real part in one variable of the datasture and complex in anthor variable. Python provides a way to overload some operators including +, -, *, /. E.g I've the following class implements complex data structure with three operators(+, - , *)
class ComplexNDArray(object):
def __init__(self, real, imaginary):
self.real = real
self.imaginary = imaginary
#property
def real(self):
return self.__real
#real.setter
def real(self, value):
if type(value) == np.ndarray:
self.__real = value
elif isinstance(value, (int, float, list, tuple)):
self.__real = np.array(value)
else:
raise ValueError("Unsupported type value:%s" % (str(type(value))))
#property
def imaginary(self):
return self.__imaginary
#imaginary.setter
def imaginary(self, value):
if type(value) == np.ndarray:
self.__imaginary = value
elif isinstance(value, (int, float, list, tuple)):
self.__imaginary = np.array(value)
else:
raise ValueError("Unsupported type value:%s" % (str(type(value))))
def __add__(self, other):
real = self.real + other.real
imaginary = self.imaginary + other.imaginary
return ComplexNDArray(real, imaginary)
def __sub__(self, other):
real = self.real - other.real
imaginary = self.imaginary - other.imaginary
return ComplexNDArray(real, imaginary)
def __mul__(self, other):
real = self.real * other.real - self.imaginary * other.imaginary
imaginary = self.real * other.imaginary + self.imaginary * other.real
return ComplexNDArray(real, imaginary)
def __str__(self):
return str(self.real) + "+"+str(self.imaginary)+"i"
Now you can use this data structure to do some operations.
a = np.array([1, 2,3])
b = np.array([4, 5, 1])
c = np.array([4, 7,3])
d = np.array([5, 1,7])
cmplx = ComplexNDArray(a, b)
cmplx2 = ComplexNDArray(c, d)
print(cmplx) # [1 2 3]+[4 5 1]i
print(cmplx2) # [4 7 3]+[5 1 7]i
print(cmplx+cmplx2) # [5 9 6]+[9 6 8]i
print(cmplx-cmplx2) # [-3 -5 0]+[-1 4 -6]i
print(cmplx*cmplx2) # [-16 9 2]+[21 37 24]i
I'm trying to implement ECDSA using python as part of my homework, I have a function named multiplication which takes two arguments Point P and t calculates B= tP.I have implemented this algorith based on iterative double and add algorithm on this wikipedia page the problem is when p coordination is small(one or two digits), the algorithm works fine but when coordination is large (about 70 digits) the result is different than what it supposed to be. here is the part of my code which calculates multiplication:
def addition(self, p, q):
if p.is_infinite:
return q
elif q.is_infinite:
return p
else :
if (q.x - p.x) == 0:
point = Point.Point(0, 0)
point.is_infinite = True
return point
s = int(((q.y - p.y) * Utils.Utils.mode_inverse(q.x - p.x, self.prime)) % self.prime)
xr = int((math.pow(s, 2) - p.x - q.x) % self.prime)
yr = int(((s * (p.x - xr)) - p.y) % self.prime)
r = Point.Point(xr, yr)
return r
def double(self, p):
if p.is_infinite:
return p
if p.y == 0:
point = Point.Point(0, 0)
point.is_infinite = True
return point
s = int((((3 * math.pow(p.x, 2)) + self.a) * Utils.Utils.mode_inverse(2 * p.y, self.prime)) % self.prime)
xr = int((math.pow(s, 2) - p.x - p.x) % self.prime)
yr = int(((s * (p.x - xr)) - p.y) % self.prime)
r = Point.Point(xr, yr)
return r
def multiplication(self, p, t):
bin_t = bin(t)[2:]
Q = Point.Point(p.x, p.y)
Q.is_infinite = True
for i, digit in enumerate(bin_t):
Q = self.double(Q)
if digit == '1':
Q = self.addition(Q, p)
return Q
Here is my Util class:
class Utils(object):
#staticmethod
def mode_inverse(a, m):
return pow(a, m - 2, m)
Here is my Point class:
class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y
self.is_infinite = False
I use Curve P-224 parameters which are:
p = 26959946667150639794667015087019630673557916260026308143510066298881
a = -3
b = 18958286285566608000408668544493926415504680968679321075787234672564
Gx = 19277929113566293071110308034699488026831934219452440156649784352033
Gy = 19926808758034470970197974370888749184205991990603949537637343198772
according to calculator http://www.christelbach.com/eccalculator.aspx I should get this result for calculating 2G:
Px = 11838696407187388799350957250141035264678915751356546206913969278886
Py = 2966624012289393637077209076615926844583158638456025172915528198331
but what I actually get is:
Px = 15364035107168693070617763393106849380516103015030577748254379737088
Py = 7033137909116168824469040716130881489351924269422358605872723100109
Is there any way to fix this?
This was just a guess:
math.pow returns a floating point number (which has finite precision). I'd suggest using e.g. s.x * s.x instead of math.pow(s.x,2) in case the issue is hitting precision issues with bigger numbers.
I just made a generic number class.
this class is so simple, descriptions are below
from any ordered character list, make number class representing that ordered character list.
create_number_class("01") returns binary number class
create_number_class("0123456789") returns decimal number class
create_number_class("abcdefghij") return decimal number class but representing each digit as a alphabet.
belows is generic number class definition.
I think it is well-made class definition.
are there something needed improvement in that class definition?
thank you all. always.
ex)
ABC_Class = create_number_class("abc")
x = ABC_Class("baa")
y = ABC_Class("bbb")
print(x+y)
#output digits: abc, v: cbb, decimal_v: 22
below is class definition
def create_number_class(alphabet):
class temp(object):
digits = alphabet
def __init__(self, v):
self.v = v
self.decimal_v = self.to_decimal(self)
#staticmethod
def to_decimal(self):
r = 0
for i in range(0, len(self.v)):
r += len(temp.digits)**(len(self.v)-i-1)*(temp.digits.index(self.v[i]))
return r
#classmethod
def from_decimal(cls, decimal_v):
r = []
mod = len(temp.digits)
if decimal_v < mod:
return cls(temp.digits[decimal_v])
while True:
remainder = decimal_v % mod
r.append(remainder)
decimal_v = int((decimal_v - remainder)/ mod)
if decimal_v < mod:
r.append(decimal_v)
break
r = "".join(list(reversed([temp.digits[x] for x in r])))
#r = "".join(list(reversed([str(temp.digits.index(str(x))) for x in r])))
return cls(r)
def __add__(self, other):
return temp.from_decimal(self.decimal_v+other.decimal_v)
def __sub__(self, other):
return temp.from_decimal(self.decimal_v-other.decimal_v)
def __mul__(self, other):
return temp.from_decimal(self.decimal_v*other.decimal_v)
def __floordiv__(self, other):
return temp.from_decimal(self.decimal_v//other.decimal_v)
def __str__(self):
return "digits: {}, v: {}, decimal_v: {}".format(temp.digits, self.v, self.decimal_v)
def convert_to(self, new_class):
return new_class.from_decimal(self.decimal_v)
return temp
below are example
BinClass = create_number_class("01")
DecimalClass = create_number_class("0123456789")
x = BinClass("111")
x = BinClass("1000")
y = BinClass("10")
HexClass = create_number_class('0123456789ABCDEF')
x = HexClass('1')
y = HexClass('AA')
print(x+y)
print(x-y)
print(x*y)
print(x//y)
print(x.convert_to(DecimalClass))
isinstance(x, BinClass)