|
4 | 4 |
|
5 | 5 | @author: Omar Belghaouti |
6 | 6 | """ |
| 7 | +from termcolor import colored |
7 | 8 | from math import sqrt |
8 | 9 | # Complex class for complex number manipulations |
9 | 10 | class Complex(): |
10 | 11 | # Constructor |
11 | | - def __init__(self, re=0, im=0): |
| 12 | + # re : is the real part of complex number |
| 13 | + # im : is the imaginary part of complex number |
| 14 | + # restore : whenever an error occurs on any operation of a complex number, the last instance will be restored (By default it's true) |
| 15 | + def __init__(self, re=0, im=0, restore=True): |
12 | 16 | self.re = re |
13 | 17 | self.im = im |
| 18 | + self.restore = restore |
14 | 19 | # Operator overloading 1 : + |
15 | 20 | def __add__(self, other): |
16 | | - if not isinstance(other, Complex): |
17 | | - other = Complex(other) |
18 | | - return Complex(self.re + other.re, self.im + other.im) |
| 21 | + try: |
| 22 | + if other is None: |
| 23 | + raise ValueError('The second number is None') |
| 24 | + if not isinstance(other, Complex): |
| 25 | + other = Complex(other) |
| 26 | + return Complex(self.re + other.re, self.im + other.im) |
| 27 | + except ValueError as err: |
| 28 | + print(colored('{}: {}'.format(err.__class__.__name__, err), 'red')) |
19 | 29 | # Operator overloading 2 : - |
20 | 30 | def __sub__(self, other): |
21 | | - if not isinstance(other, Complex): |
22 | | - other = Complex(other) |
23 | | - return Complex(self.re - other.re, self.im - other.im) |
| 31 | + try: |
| 32 | + if other is None: |
| 33 | + raise ValueError('The second number is None') |
| 34 | + if not isinstance(other, Complex): |
| 35 | + other = Complex(other) |
| 36 | + return Complex(self.re - other.re, self.im - other.im) |
| 37 | + except ValueError as err: |
| 38 | + print(colored('{}: {}'.format(err.__class__.__name__, err), 'red')) |
24 | 39 | # Operator overloading 3 : * |
25 | 40 | def __mul__(self, other): |
26 | | - if not isinstance(other, Complex): |
27 | | - other = Complex(other) |
28 | | - return Complex(self.re * other.re - self.im * other.im, self.re * other.im + self.im * other.re) |
| 41 | + try: |
| 42 | + if other is None: |
| 43 | + raise ValueError('The second number is None') |
| 44 | + if not isinstance(other, Complex): |
| 45 | + other = Complex(other) |
| 46 | + return Complex(self.re * other.re - self.im * other.im, self.re * other.im + self.im * other.re) |
| 47 | + except ValueError as err: |
| 48 | + print(colored('{}: {}'.format(err.__class__.__name__, err), 'red')) |
29 | 49 | # Operator overloading 4 : / |
30 | 50 | def __truediv__(self, other): |
31 | 51 | try: |
| 52 | + if other is None: |
| 53 | + raise ValueError('The second number is None') |
32 | 54 | if not isinstance(other, Complex): |
33 | 55 | other = Complex(other) |
34 | 56 | den = other * other.con() |
35 | 57 | num = self * other.con() |
| 58 | + if den.re == 0 and self.restore: |
| 59 | + print(colored('Float division by zero', 'red')) |
| 60 | + print(colored('Restoring last number', 'green')) |
| 61 | + return Complex(self.re, self.im) |
36 | 62 | return Complex(num.re / den.re, num.im / den.re) |
37 | | - except ZeroDivisionError as err: |
38 | | - print('Error: {}'.format(err)) |
| 63 | + except (ZeroDivisionError, ValueError) as err: |
| 64 | + print(colored('{}: {}'.format(err.__class__.__name__, err), 'red')) |
39 | 65 | # Operator overloading 5 : // |
40 | 66 | def __floordiv__(self, other): |
41 | 67 | try: |
| 68 | + if other is None: |
| 69 | + raise ValueError('The second number is None') |
42 | 70 | if not isinstance(other, Complex): |
43 | 71 | other = Complex(other) |
44 | 72 | den = other * other.con() |
45 | 73 | num = self * other.con() |
| 74 | + if den.re == 0 and self.restore: |
| 75 | + print(colored('Float division by zero', 'red')) |
| 76 | + print(colored('Restoring last number', 'green')) |
| 77 | + return Complex(self.re, self.im) |
46 | 78 | return Complex(num.re // den.re, num.im // den.re) |
47 | | - except ZeroDivisionError as err: |
48 | | - print('Error: {}'.format(err)) |
| 79 | + except (ZeroDivisionError, ValueError) as err: |
| 80 | + print(colored('{}: {}'.format(err.__class__.__name__, err), 'red')) |
49 | 81 | def __gt__(self, other): |
50 | | - if not isinstance(other, Complex): |
51 | | - other = Complex(other) |
52 | | - return self.mod() > other.mod() |
| 82 | + try: |
| 83 | + if other is None: |
| 84 | + raise ValueError('The second number is None') |
| 85 | + if not isinstance(other, Complex): |
| 86 | + other = Complex(other) |
| 87 | + return self.mod() > other.mod() |
| 88 | + except ValueError as err: |
| 89 | + print(colored('{}: {}'.format(err.__class__.__name__, err), 'red')) |
53 | 90 | # Operator overloading 7 : >= |
54 | 91 | def __ge__(self, other): |
55 | | - if not isinstance(other, Complex): |
56 | | - other = Complex(other) |
57 | | - return self.mod() >= other.mod() |
| 92 | + try: |
| 93 | + if other is None: |
| 94 | + raise ValueError('The second number is None') |
| 95 | + if not isinstance(other, Complex): |
| 96 | + other = Complex(other) |
| 97 | + return self.mod() >= other.mod() |
| 98 | + except ValueError as err: |
| 99 | + print(colored('{}: {}'.format(err.__class__.__name__, err), 'red')) |
58 | 100 | # Operator overloading 8: < |
59 | 101 | def __lt__(self, other): |
60 | | - if not isinstance(other, Complex): |
61 | | - other = Complex(other) |
62 | | - return not self >= other |
| 102 | + try: |
| 103 | + if other is None: |
| 104 | + raise ValueError('The second number is None') |
| 105 | + if not isinstance(other, Complex): |
| 106 | + other = Complex(other) |
| 107 | + return not self >= other |
| 108 | + except ValueError as err: |
| 109 | + print(colored('{}: {}'.format(err.__class__.__name__, err), 'red')) |
63 | 110 | # Operator overloading 9: <= |
64 | 111 | def __le__(self, other): |
65 | | - if not isinstance(other, Complex): |
66 | | - other = Complex(other) |
67 | | - return not self > other |
| 112 | + try: |
| 113 | + if other is None: |
| 114 | + raise ValueError('The second number is None') |
| 115 | + if not isinstance(other, Complex): |
| 116 | + other = Complex(other) |
| 117 | + return not self > other |
| 118 | + except ValueError as err: |
| 119 | + print(colored('{}: {}'.format(err.__class__.__name__, err), 'red')) |
68 | 120 | # Operator overloading 10: == |
69 | 121 | def __eq__(self, other): |
70 | | - if not isinstance(other, Complex): |
71 | | - other = Complex(other) |
72 | | - return (self.re == other.re) and (self.im == other.im) |
| 122 | + try: |
| 123 | + if other is None: |
| 124 | + raise ValueError('The second number is None') |
| 125 | + if not isinstance(other, Complex): |
| 126 | + other = Complex(other) |
| 127 | + return (self.re == other.re) and (self.im == other.im) |
| 128 | + except ValueError: |
| 129 | + print(colored('{}: {}'.format(err.__class__.__name__, err), 'red')) |
73 | 130 | # Operator overloading 11: != |
74 | 131 | def __ne__(self, other): |
75 | | - if not isinstance(other, Complex): |
76 | | - other = Complex(other) |
77 | | - return not self == other |
| 132 | + try: |
| 133 | + if other is None: |
| 134 | + raise ValueError('The second number is None') |
| 135 | + if not isinstance(other, Complex): |
| 136 | + other = Complex(other) |
| 137 | + return not self == other |
| 138 | + except ValueError as err: |
| 139 | + print(colored('{}: {}'.format(err.__class__.__name__, err), 'red')) |
78 | 140 | # Operator overloading 12: += |
79 | 141 | def __iadd__(self, other): |
80 | | - if not isinstance(other, Complex): |
81 | | - other = Complex(other) |
82 | | - self.re += other.re |
83 | | - self.im += other.im |
84 | | - return Complex(self.re, self.im) |
| 142 | + try: |
| 143 | + if other is None: |
| 144 | + raise ValueError('The second number is None') |
| 145 | + if not isinstance(other, Complex): |
| 146 | + other = Complex(other) |
| 147 | + self.re += other.re |
| 148 | + self.im += other.im |
| 149 | + return Complex(self.re, self.im) |
| 150 | + except ValueError as err: |
| 151 | + print(colored('{}: {}'.format(err.__class__.__name__, err), 'red')) |
85 | 152 | # Operator overloading 13: -= |
86 | 153 | def __isub__(self, other): |
87 | | - if not isinstance(other, Complex): |
88 | | - other = Complex(other) |
89 | | - self.re -= other.re |
90 | | - self.im -= other.im |
91 | | - return Complex(self.re, self.im) |
| 154 | + try: |
| 155 | + if other is None: |
| 156 | + raise ValueError('The second number is None') |
| 157 | + if not isinstance(other, Complex): |
| 158 | + other = Complex(other) |
| 159 | + self.re -= other.re |
| 160 | + self.im -= other.im |
| 161 | + return Complex(self.re, self.im) |
| 162 | + except ValueError as err: |
| 163 | + print(colored('{}: {}'.format(err.__class__.__name__, err), 'red')) |
92 | 164 | # Operator overloading 14: *= |
93 | 165 | def __imul__(self, other): |
94 | | - if not isinstance(other, Complex): |
95 | | - other = Complex(other) |
96 | | - self.re = self.re * other.re - self.im * other.im |
97 | | - self.im = self.re * other.im + self.im * other.re |
98 | | - return Complex(self.re, self.im) |
| 166 | + try: |
| 167 | + if other is None: |
| 168 | + raise ValueError('The second number is None') |
| 169 | + if not isinstance(other, Complex): |
| 170 | + other = Complex(other) |
| 171 | + self.re = self.re * other.re - self.im * other.im |
| 172 | + self.im = self.re * other.im + self.im * other.re |
| 173 | + return Complex(self.re, self.im) |
| 174 | + except ValueError as err: |
| 175 | + print(colored('{}: {}'.format(err.__class__.__name__, err), 'red')) |
99 | 176 | # Operator overloading 15: /= |
100 | 177 | def __idiv__(self, other): |
101 | 178 | try: |
| 179 | + if other is None: |
| 180 | + raise ValueError('The second number is None') |
102 | 181 | if not isinstance(other, Complex): |
103 | 182 | other = Complex(other) |
104 | 183 | den = other * other.con() |
105 | 184 | num = self * other.con() |
| 185 | + if den.re == 0 and self.restore: |
| 186 | + print(colored('Float division by zero', 'red')) |
| 187 | + print(colored('Restoring last number', 'green')) |
| 188 | + return Complex(self.re, self.im) |
106 | 189 | self.re = num.re / den.re |
107 | 190 | self.im = num.im / den.re |
108 | | - return Complex(self.re, self.im) |
109 | | - except ZeroDivisionError as err: |
110 | | - print('Error: {}'.format(err)) |
| 191 | + return Complex(re, im) |
| 192 | + except (ZeroDivisionError, ValueError) as err: |
| 193 | + print(colored('{}: {}'.format(err.__class__.__name__, err), 'red')) |
111 | 194 | # Operator overloading 16: //= |
112 | 195 | def __ifloordiv__(self, other): |
113 | 196 | try: |
| 197 | + if other is None: |
| 198 | + raise ValueError('The second number is None') |
114 | 199 | if not isinstance(other, Complex): |
115 | 200 | other = Complex(other) |
116 | 201 | den = other * other.con() |
117 | 202 | num = self * other.con() |
| 203 | + if den.re == 0 and self.restore: |
| 204 | + print(colored('Float division by zero', 'red')) |
| 205 | + print(colored('Restoring last number', 'green')) |
| 206 | + return Complex(self.re, self.im) |
118 | 207 | self.re = num.re // den.re |
119 | 208 | self.im = num.im // den.re |
120 | 209 | return Complex(self.re, self.im) |
121 | | - except ZeroDivisionError as err: |
122 | | - print('Error: {}'.format(err)) |
| 210 | + except (ZeroDivisionError, ValueError) as err: |
| 211 | + print(colored('{}: {}'.format(err.__class__.__name__, err), 'red')) |
123 | 212 | ## Helper functions |
124 | 213 | # Module function to calculate the modulus of a complex number |
125 | 214 | def mod(self): |
|
0 commit comments