473,406 Members | 2,745 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,406 software developers and data experts.

overloading rational add

TMS
119 100+
I have overloaded the basic addition operator, adding 2 fractions, but now I'm having trouble adding a fraction with a non fraction, ie: 3/4 + 1.

Here is part of my program:

Expand|Select|Wrap|Line Numbers
  1. def gcd(a, b):
  2.     while b:
  3.         a, b = b, a%b
  4.     return abs(a)
  5.  
  6. class Rational:
  7.     """
  8.     function to initialize variables
  9.     """
  10.     def __init__(self, num, den = 1):
  11.         assert den != 0         #make sure denominator isn't 0
  12.         self.n = num
  13.         self.d = den
  14.         reduced = gcd(num, den) # reduce fraction
  15.         self.n = num/reduced
  16.         self.d= den/reduced
  17.     """
  18.     function to print answer as a string, strips trailing L on longs)
  19.     """
  20.     def __repr__(self):
  21.         return '(%d/%d)' % (self.n, self.d)
  22.     """
  23.     function to overload addition operator to add 2 fractions
  24.     """
  25.     def __add__(self, terms):
  26.         return Rational(self.n*terms.d + terms.n*self.d, self.d*terms.d)
  27.  
  28.  
This is the error I get:
Traceback (most recent call last):
File "C:\Python25\Rational.py", line 87, in <module>
print " a + 1:", a + 1
File "C:\Python25\Rational.py", line 38, in __add__
return Rational(self.n*terms.d + terms.n*self.d, self.d*terms.d)
AttributeError: 'int' object has no attribute 'd'

So, I figured what I need to do is give the whole number a denominator, and that didn't work. Can anyone walk me through this?

Thank you !

TMS
Feb 15 '07 #1
12 2268
bartonc
6,596 Expert 4TB
I have overloaded the basic addition operator, adding 2 fractions, but now I'm having trouble adding a fraction with a non fraction, ie: 3/4 + 1.

This is the error I get:
Traceback (most recent call last):
File "C:\Python25\Rational.py", line 87, in <module>
print " a + 1:", a + 1
File "C:\Python25\Rational.py", line 38, in __add__
return Rational(self.n*terms.d + terms.n*self.d, self.d*terms.d)
AttributeError: 'int' object has no attribute 'd'

So, I figured what I need to do is give the whole number a denominator, and that didn't work. Can anyone walk me through this?

Thank you !

TMS
What you need to do is check the type of the argument in question and either add differently if it's not isinstance(arg, Rational) or convert it to a Rational type object before you add. The former is probably the way to go.
Expand|Select|Wrap|Line Numbers
  1. def gcd(a, b):
  2.     while b:
  3.         a, b = b, a%b
  4.     return abs(a)
  5.  
  6. class Rational:
  7.     def __init__(self, num, den = 1):
  8.     """
  9.     function to initialize variables
  10.     """
  11.         assert den != 0         #make sure denominator isn't 0
  12.         self.n = num
  13.         self.d = den
  14.         reduced = gcd(num, den) # reduce fraction
  15.         self.n = num/reduced
  16.         self.d= den/reduced
  17.     def __repr__(self):
  18.     """
  19.     function to print answer as a string, strips trailing L on longs)
  20.     """
  21.         return '(%d/%d)' % (self.n, self.d)
  22.     def __add__(self, terms):
  23.     """
  24.     function to overload addition operator to add 2 fractions
  25.     """
  26.         if isinstance(terms, Rational):
  27.             return Rational(self.n*terms.d + terms.n*self.d, self.d*terms.d)
  28.         else:
  29.             pass    # replace with your code
Also, put the docstrings inside the def so that python's documentation features can find them.
Feb 15 '07 #2
TMS
119 100+
OK, cool. I will work on that. TY
Feb 15 '07 #3
TMS
119 100+
[font=Verdana][size=2]THANK you! I was working on that and couldn't figure it out. The instance thing helped because it stopped it from going back through the __init__.... Hadn't heard of the instance thing. Thanks![/size][/font]
Feb 15 '07 #4
bartonc
6,596 Expert 4TB
OK, cool. I will work on that. TY
Ya know what's really cool? When you post back with working code so others can make use of the knowledge that you have gained.
Feb 15 '07 #5
TMS
119 100+
kk, lol, here it is:

Expand|Select|Wrap|Line Numbers
  1.  def __add__(self, terms):
  2.         """
  3.         function to overload addition operator to add 2 fractions or a fraction
  4.             and a whole number
  5.         """
  6.         if isinstance(terms, Rational):
  7.             return Rational(self.n*terms.d + terms.n*self.d, self.d*terms.d)
  8.         else:
  9.             terms = Rational(terms, 1)
  10.             return Rational(self.n*terms.d + terms.n*self.d, self.d*terms.d)
  11.  
works great.

I have another question regarding floats. If I pass a float, I get an error (obviously), so I tried to fix it by defining a float function:

Expand|Select|Wrap|Line Numbers
  1. def __float__(self):
  2.         return float(self.n)
  3.  
Silly me, thought I could get away that easy. But no, I get an error that looks like this when I try to pass Rational(1.3) with a default denominator of 1:


Traceback (most recent call last):
File "C:\Python25\Rational.py", line 106, in <module>
print " c:", c
File "C:\Python25\Rational.py", line 34, in __repr__
return '(%d/%d)' % (self.n, self.d)
TypeError: int argument required

Any hints?
Feb 15 '07 #6
bartonc
6,596 Expert 4TB
I have another question regarding floats. If I pass a float, I get an error (obviously), so I tried to fix it by defining a float function:

Expand|Select|Wrap|Line Numbers
  1. def __float__(self):
  2.         return float(self.n)
  3.  
Silly me, thought I could get away that easy. But no, I get an error that looks like this when I try to pass Rational(1.3) with a default denominator of 1:


Traceback (most recent call last):
File "C:\Python25\Rational.py", line 106, in <module>
print " c:", c
File "C:\Python25\Rational.py", line 34, in __repr__
return '(%d/%d)' % (self.n, self.d)
TypeError: int argument required

Any hints?
The hint is in the error msg:
"return '(%d/%d)' % (self.n, self.d)
TypeError: int argument required"
To format floats you need
Expand|Select|Wrap|Line Numbers
  1. >>> a = 10.0
  2. >>> floatStr = '%.3f' %a
  3. >>> print floatStr
  4. 10.000
  5. >>> 
Feb 16 '07 #7
bvdet
2,851 Expert Mod 2GB
kk, lol, here it is:

Expand|Select|Wrap|Line Numbers
  1.  def __add__(self, terms):
  2.         """
  3.         function to overload addition operator to add 2 fractions or a fraction
  4.             and a whole number
  5.         """
  6.         if isinstance(terms, Rational):
  7.             return Rational(self.n*terms.d + terms.n*self.d, self.d*terms.d)
  8.         else:
  9.             terms = Rational(terms, 1)
  10.             return Rational(self.n*terms.d + terms.n*self.d, self.d*terms.d)
  11.  
works great.

I have another question regarding floats. If I pass a float, I get an error (obviously), so I tried to fix it by defining a float function:

Expand|Select|Wrap|Line Numbers
  1. def __float__(self):
  2.         return float(self.n)
  3.  
Silly me, thought I could get away that easy. But no, I get an error that looks like this when I try to pass Rational(1.3) with a default denominator of 1:


Traceback (most recent call last):
File "C:\Python25\Rational.py", line 106, in <module>
print " c:", c
File "C:\Python25\Rational.py", line 34, in __repr__
return '(%d/%d)' % (self.n, self.d)
TypeError: int argument required

Any hints?
If you want to enable the input of floats, this will work for floats up to 4 decimal places:
Expand|Select|Wrap|Line Numbers
  1. def __init__(self, num, den=1):
  2.         if isinstance(num, float) or isinstance(den, float):
  3.             num, den = map(lambda x: x * 1000, [num, den])
  4.             num, den = map(int, [num, den])
  5.  
  6.         assert den != 0
  7.         reduced = gcd(num, den)
  8.         self.n = num/reduced
  9.         self.d = den/reduced
  10.  
  11. >>> a = Rational(1.33, 5.13)
  12. >>> print a
  13. (7/27)
  14. >>> 
Feb 16 '07 #8
bvdet
2,851 Expert Mod 2GB
TMS,

Sometimes I create __str__ and __repr__ methods for classes. The __str__ method will execute when the instance is printed. The __repr__ method will recreate the object when passed to eval(). Your project:
Expand|Select|Wrap|Line Numbers
  1. >>> a = Rational(3,4)
  2. >>> a
  3. Rational(3, 4)
  4. >>> print a
  5. (3/4)
  6. >>> z = repr(a)
  7. >>> z
  8. 'Rational(3, 4)'
  9. >>> z = eval(repr(a))
  10. >>> z
  11. Rational(3, 4)
  12. >>> print z
  13. (3/4)
Feb 16 '07 #9
bvdet
2,851 Expert Mod 2GB
TMS,

You can eliminate duplicate code in your __add__ method this way:
Expand|Select|Wrap|Line Numbers
  1.     def __add__(self, other):
  2.         if not isinstance(other, Rational):
  3.             other = Rational(other)
  4.         return Rational(self.n * other.d + other.n * self.d, self.d * other.d)
Feb 16 '07 #10
bvdet
2,851 Expert Mod 2GB
TMS,

A couple more suggestions and I'm done.
1. If you are overloading multiple operators in your class definition, you may want to add a __coerce__ method:
Expand|Select|Wrap|Line Numbers
  1.     def __add__(self, other):
  2.         other = self.__coerce__(other)
  3.         return Rational(self.n * other.d + other.n * self.d, self.d * other.d)
  4.  
  5.     def __coerce__(self, other):
  6.         if isinstance(other, Rational):
  7.             return other
  8.         try:
  9.             return Rational(other)
  10.         except:
  11.             raise ValueError, 'Invalid operand'
2. The assert statement is mostly used for debugging. I would prefer to test for 0 like this:
Expand|Select|Wrap|Line Numbers
  1. if den != 0:
  2.     ...... do stuff ......
  3. else:
  4.     raise ValueError, 'The denominator must not be 0'
There may be better ways.

HTH :)
Feb 16 '07 #11
bartonc
6,596 Expert 4TB
TMS,

A couple more suggestions and I'm done.
1. If you are overloading multiple operators in your class definition, you may want to add a __coerce__ method:
Expand|Select|Wrap|Line Numbers
  1.     def __add__(self, other):
  2.         other = self.__coerce__(other)
  3.         return Rational(self.n * other.d + other.n * self.d, self.d * other.d)
  4.  
  5.     def __coerce__(self, other):
  6.         if isinstance(other, Rational):
  7.             return other
  8.         try:
  9.             return Rational(other)
  10.         except:
  11.             raise ValueError, 'Invalid operand'
2. The assert statement is mostly used for debugging. I would prefer to test for 0 like this:
Expand|Select|Wrap|Line Numbers
  1. if den != 0:
  2.     ...... do stuff ......
  3. else:
  4.     raise ValueError, 'The denominator must not be 0'
There may be better ways.

HTH :)
Great suggestions BV. You are the man!
Feb 16 '07 #12
TMS
119 100+
Honestly!! Thank you! Those are great suggestions. We are just starting the unit on Exceptions so the "Try" ... will be great because I can start practicing with it. Thank you very much!


TMS
Feb 19 '07 #13

Sign in to post your reply or Sign up for a free account.

Similar topics

21
by: Mike Meyer | last post by:
PEP: XXX Title: A rational number module for Python Version: $Revision: 1.4 $ Last-Modified: $Date: 2003/09/22 04:51:50 $ Author: Mike Meyer <mwm@mired.org> Status: Draft Type: Staqndards...
20
by: Mike Meyer | last post by:
This version includes the input from various and sundry people. Thanks to everyone who contributed. <mike PEP: XXX Title: A rational number module for Python Version: $Revision: 1.4 $...
6
by: Zenon | last post by:
Folks, I am having a terrible time overloading operators. I have tried what I thought was the correct way, I tried the cheating (friend declarations), all to no avail. Sorry for posting tons of...
2
by: Brian van den Broek | last post by:
Hi all, I guess it is more of a maths question than a programming one, but it involves use of the decimal module, so here goes: As a self-directed learning exercise I've been working on a...
18
by: uday | last post by:
Does C supports overloading. I am thinking no. But some people are saying yes. If yes how. Please answer with examples. Also in c++ size of empty class is one. why. and what are the default...
8
by: andrew browning | last post by:
I am getting an istream overloading error that looks like this: error: no match for 'operator>>' in 'ins >> target->abrowning_rational::Rational::numerator' Below is the .h file: #ifndef...
6
by: penny | last post by:
In this assignment we shall look at a possible representation of rational numbers in java using objects. The java language represents rational numbers using the same representation used for other...
4
by: =?ISO-8859-1?Q?Tom=E1s_=D3_h=C9ilidhe?= | last post by:
Operator overloads are just like any other member function, you can make them do whatever you want. However, of course, we might expect them to behave in a certain way. The ++ operator should...
5
by: anumliaqat | last post by:
hello!! i hav a problem.my program is giving correct outputs for some inputs but wrong results for others. for example if u give (4 2 2)&(2 1 2) to it,it shows all results correct....
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.