engineering-notation 0.12.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- engineering_notation-0.12.0/PKG-INFO +111 -0
- engineering_notation-0.12.0/engineering_notation/__init__.py +4 -0
- engineering_notation-0.12.0/engineering_notation/eng_notation.py +555 -0
- engineering_notation-0.12.0/engineering_notation/version.py +3 -0
- engineering_notation-0.12.0/engineering_notation.egg-info/PKG-INFO +111 -0
- engineering_notation-0.12.0/engineering_notation.egg-info/SOURCES.txt +10 -0
- engineering_notation-0.12.0/engineering_notation.egg-info/dependency_links.txt +1 -0
- engineering_notation-0.12.0/engineering_notation.egg-info/top_level.txt +1 -0
- engineering_notation-0.12.0/pyproject.toml +14 -0
- engineering_notation-0.12.0/readme.md +104 -0
- engineering_notation-0.12.0/setup.cfg +4 -0
- engineering_notation-0.12.0/tests/test_engnum.py +590 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: engineering-notation
|
|
3
|
+
Version: 0.12.0
|
|
4
|
+
Summary: Easy engineering notation
|
|
5
|
+
Requires-Python: >=3.11
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
|
|
8
|
+
[](https://github.com/slightlynybbled/engineering_notation/actions/workflows/unittest.yml)
|
|
9
|
+
|
|
10
|
+
# Purpose
|
|
11
|
+
|
|
12
|
+
To easily work with human-readable engineering notation. I wrote this as a quick tool for my own use.
|
|
13
|
+
I found that I was writing the same functionality into multiple packages and would like a quick pip-installable
|
|
14
|
+
package to take care of this manipulation for me. The package should be easily extended for other use cases.
|
|
15
|
+
The package is unit-less, so only operates on numeric values. Unit detection may be added in future versions.
|
|
16
|
+
|
|
17
|
+
More information may be found at [for(embed)](http://forembed.com/engineering-notation-in-python.html).
|
|
18
|
+
|
|
19
|
+
# Installation
|
|
20
|
+
|
|
21
|
+
Install using pip: `pip install engineering_notation`.
|
|
22
|
+
|
|
23
|
+
# Usage
|
|
24
|
+
|
|
25
|
+
There are multiple ways of initializing a number to a particular value, but a string is the preferred method:
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
>>> from engineering_notation import EngNumber
|
|
29
|
+
>>> EngNumber('10k')
|
|
30
|
+
10k
|
|
31
|
+
>>> EngNumber('10000')
|
|
32
|
+
10k
|
|
33
|
+
>>> EngNumber(10000)
|
|
34
|
+
10k
|
|
35
|
+
>>> EngNumber(10000.0)
|
|
36
|
+
10k
|
|
37
|
+
>>> EngNumber(1e4)
|
|
38
|
+
10k
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Where decimals are involved, we use a default precision of 2 digits:
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
>>> EngNumber('4.99k')
|
|
45
|
+
4.99k
|
|
46
|
+
>>> EngNumber('4.9k')
|
|
47
|
+
4.90k
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
This behavior can truncate your results in some cases, and cause your number to round. To specify more or less
|
|
51
|
+
digits, simply specify the precision in the declaration:
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
>>> EngNumber('4.999k')
|
|
55
|
+
5k
|
|
56
|
+
>>> EngNumber('4.999k', precision=3)
|
|
57
|
+
4.999k
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Most operations that you would perform on numeric values are valid, although all operations are not implemented:
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
>>> EngNumber('2.2k') * 2
|
|
64
|
+
4.40k
|
|
65
|
+
>>> 2 * EngNumber('2.2k')
|
|
66
|
+
4.40k
|
|
67
|
+
>>> EngNumber(1.2) > EngNumber('3.3k')
|
|
68
|
+
False
|
|
69
|
+
>>> EngNumber(1.2) <= EngNumber('3.3k')
|
|
70
|
+
True
|
|
71
|
+
>>> EngNumber('3.3k') == EngNumber(3300)
|
|
72
|
+
True
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
All of the above operations are also possible on the `EngUnit()` class as well. The only difference is
|
|
76
|
+
that units must match for addition/subtraction/comparison operations. Although multiplication and division
|
|
77
|
+
operations will work numerically, they may not always be strictly correct. This is because EngUnit is not
|
|
78
|
+
intended to replace a computer algebra system!
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
>>> EngUnit('2s') / EngUnit('4rotations')
|
|
82
|
+
0.5s/rotations
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Additionally, since there are 'reserved' letters for sizing the number, you must be careful with your units!
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
>>> EngUnit('2mm')
|
|
89
|
+
2mm # <<< this value equivalent to "0.002m"
|
|
90
|
+
>>> EngUnit('2meter')
|
|
91
|
+
2meter # <<< this value is equivalent to "0.002eter", the "m" was used to scale the unit!
|
|
92
|
+
>>> EngUnit('2', unit='meter') # <<< this will work better
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
# Contributions
|
|
96
|
+
|
|
97
|
+
Contributions are welcome. Feel free to make feature requests in the issues.
|
|
98
|
+
|
|
99
|
+
## Test Installation
|
|
100
|
+
|
|
101
|
+
If you are developing, you probably want to perform a local editable installation:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
uv run pip install -e .
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Testing
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
uv run python -m pytest
|
|
111
|
+
```
|
|
@@ -0,0 +1,555 @@
|
|
|
1
|
+
from decimal import Decimal
|
|
2
|
+
from string import digits
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
from typing import Optional
|
|
6
|
+
|
|
7
|
+
try:
|
|
8
|
+
import numpy
|
|
9
|
+
except ImportError:
|
|
10
|
+
pass
|
|
11
|
+
|
|
12
|
+
_suffix_lookup = {
|
|
13
|
+
'y': 'e-24',
|
|
14
|
+
'z': 'e-21',
|
|
15
|
+
'a': 'e-18',
|
|
16
|
+
'f': 'e-15',
|
|
17
|
+
'p': 'e-12',
|
|
18
|
+
'n': 'e-9',
|
|
19
|
+
'u': 'e-6',
|
|
20
|
+
'm': 'e-3',
|
|
21
|
+
'': 'e0',
|
|
22
|
+
'k': 'e3',
|
|
23
|
+
'M': 'e6',
|
|
24
|
+
'G': 'e9',
|
|
25
|
+
'T': 'e12',
|
|
26
|
+
'P': 'e15',
|
|
27
|
+
'E': 'e18',
|
|
28
|
+
'Z': 'e21',
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
_exponent_lookup_scaled = {
|
|
32
|
+
'-54': 'y',
|
|
33
|
+
'-51': 'z',
|
|
34
|
+
'-48': 'a',
|
|
35
|
+
'-45': 'f',
|
|
36
|
+
'-42': 'p',
|
|
37
|
+
'-39': 'n',
|
|
38
|
+
'-36': 'u',
|
|
39
|
+
'-33': 'm',
|
|
40
|
+
'-30': '',
|
|
41
|
+
'-27': 'k',
|
|
42
|
+
'-24': 'M',
|
|
43
|
+
'-21': 'G',
|
|
44
|
+
'-18': 'T',
|
|
45
|
+
'-15': 'P',
|
|
46
|
+
'-12': 'E',
|
|
47
|
+
'-9': 'Z',
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class EngUnit:
|
|
52
|
+
"""
|
|
53
|
+
Represents an engineering number, complete with units
|
|
54
|
+
"""
|
|
55
|
+
def __init__(self, value,
|
|
56
|
+
precision=2, significant=0, unit: Optional[str] = None, separator=""):
|
|
57
|
+
"""
|
|
58
|
+
Initialize engineering with units
|
|
59
|
+
:param value: the desired value in the form of a string, int, or float
|
|
60
|
+
:param precision: the number of decimal places
|
|
61
|
+
:param significant: the number of significant digits
|
|
62
|
+
if given, significant takes precendence over precision
|
|
63
|
+
"""
|
|
64
|
+
suffix_keys = [key for key in _suffix_lookup.keys() if key != '']
|
|
65
|
+
self.unit = unit
|
|
66
|
+
|
|
67
|
+
if isinstance(value, str):
|
|
68
|
+
# parse the string into unit and engineering number
|
|
69
|
+
new_value = ''
|
|
70
|
+
v_index = 0
|
|
71
|
+
for c in value:
|
|
72
|
+
if (c in digits) or (c in ['.', '-']) or (c in suffix_keys):
|
|
73
|
+
new_value += c
|
|
74
|
+
v_index += 1
|
|
75
|
+
else:
|
|
76
|
+
break
|
|
77
|
+
|
|
78
|
+
if self.unit is None and len(value) >= v_index:
|
|
79
|
+
self.unit = value[v_index:]
|
|
80
|
+
|
|
81
|
+
self.eng_num = EngNumber(new_value, precision,
|
|
82
|
+
significant, separator)
|
|
83
|
+
|
|
84
|
+
else:
|
|
85
|
+
self.eng_num = EngNumber(value, precision, significant, separator)
|
|
86
|
+
|
|
87
|
+
def __repr__(self):
|
|
88
|
+
"""
|
|
89
|
+
Returns the object representation
|
|
90
|
+
:return: a string representing the engineering number
|
|
91
|
+
"""
|
|
92
|
+
unit = self.unit if self.unit else ''
|
|
93
|
+
return str(self.eng_num) + unit
|
|
94
|
+
|
|
95
|
+
def __str__(self):
|
|
96
|
+
"""
|
|
97
|
+
Returns the string representation
|
|
98
|
+
:return: a string representing the engineering number
|
|
99
|
+
"""
|
|
100
|
+
return self.__repr__()
|
|
101
|
+
|
|
102
|
+
def __int__(self):
|
|
103
|
+
"""
|
|
104
|
+
Implements the 'int()' method
|
|
105
|
+
:return:
|
|
106
|
+
"""
|
|
107
|
+
return int(self.eng_num)
|
|
108
|
+
|
|
109
|
+
def __float__(self):
|
|
110
|
+
"""
|
|
111
|
+
Implements the 'float()' method
|
|
112
|
+
:return:
|
|
113
|
+
"""
|
|
114
|
+
return float(self.eng_num)
|
|
115
|
+
|
|
116
|
+
def __add__(self, other):
|
|
117
|
+
"""
|
|
118
|
+
Add two engineering numbers, with units
|
|
119
|
+
:param other: EngNum, str, float, or int
|
|
120
|
+
:return: result
|
|
121
|
+
"""
|
|
122
|
+
if not isinstance(other, EngNumber):
|
|
123
|
+
other = EngUnit(str(other))
|
|
124
|
+
|
|
125
|
+
if self.unit != other.unit:
|
|
126
|
+
raise AttributeError('units do not match')
|
|
127
|
+
|
|
128
|
+
return EngUnit(str(self.eng_num + other.eng_num) + self.unit)
|
|
129
|
+
|
|
130
|
+
def __radd__(self, other):
|
|
131
|
+
"""
|
|
132
|
+
Add two engineering numbers, with units
|
|
133
|
+
:param other: EngNum, str, float, or int
|
|
134
|
+
:return: result
|
|
135
|
+
"""
|
|
136
|
+
return self.__add__(other)
|
|
137
|
+
|
|
138
|
+
def __sub__(self, other):
|
|
139
|
+
"""
|
|
140
|
+
Subtract two engineering numbers, with units
|
|
141
|
+
:param other: EngNum, str, float, or int
|
|
142
|
+
:return: result
|
|
143
|
+
"""
|
|
144
|
+
if not isinstance(other, EngNumber):
|
|
145
|
+
other = EngUnit(str(other))
|
|
146
|
+
|
|
147
|
+
if self.unit != other.unit:
|
|
148
|
+
raise AttributeError('units do not match')
|
|
149
|
+
|
|
150
|
+
return EngUnit(str(self.eng_num - other.eng_num) + self.unit)
|
|
151
|
+
|
|
152
|
+
def __rsub__(self, other):
|
|
153
|
+
"""
|
|
154
|
+
Subtract two engineering numbers, with units
|
|
155
|
+
:param other: EngNum, str, float, or int
|
|
156
|
+
:return: result
|
|
157
|
+
"""
|
|
158
|
+
if not isinstance(other, EngNumber):
|
|
159
|
+
other = EngUnit(str(other))
|
|
160
|
+
|
|
161
|
+
if self.unit != other.unit:
|
|
162
|
+
raise AttributeError('units do not match')
|
|
163
|
+
|
|
164
|
+
return EngUnit(str(other.eng_num - self.eng_num) + self.unit)
|
|
165
|
+
|
|
166
|
+
def __mul__(self, other):
|
|
167
|
+
"""
|
|
168
|
+
Multiply two engineering numbers, with units
|
|
169
|
+
:param other: EngNum, str, float, or int
|
|
170
|
+
:return: result
|
|
171
|
+
"""
|
|
172
|
+
if not isinstance(other, EngNumber):
|
|
173
|
+
other = EngUnit(str(other))
|
|
174
|
+
|
|
175
|
+
return EngUnit(str(self.eng_num * other.eng_num)
|
|
176
|
+
+ self.unit + other.unit)
|
|
177
|
+
|
|
178
|
+
def __rmul__(self, other):
|
|
179
|
+
"""
|
|
180
|
+
Multiply two engineering numbers, with units
|
|
181
|
+
:param other: EngNum, str, float, or int
|
|
182
|
+
:return: result
|
|
183
|
+
"""
|
|
184
|
+
return self.__mul__(other)
|
|
185
|
+
|
|
186
|
+
def __truediv__(self, other):
|
|
187
|
+
"""
|
|
188
|
+
Divide two engineering numbers, with units
|
|
189
|
+
:param other: EngNum, str, float, or int
|
|
190
|
+
:return: result
|
|
191
|
+
"""
|
|
192
|
+
if not isinstance(other, EngNumber):
|
|
193
|
+
other = EngUnit(str(other))
|
|
194
|
+
|
|
195
|
+
new_unit = ''
|
|
196
|
+
if self.unit:
|
|
197
|
+
new_unit += self.unit
|
|
198
|
+
if other.unit:
|
|
199
|
+
new_unit += '/' + other.unit
|
|
200
|
+
|
|
201
|
+
return EngUnit(str(self.eng_num / other.eng_num) + new_unit)
|
|
202
|
+
|
|
203
|
+
def __rtruediv__(self, other):
|
|
204
|
+
"""
|
|
205
|
+
Divide two engineering numbers, with units
|
|
206
|
+
:param other: EngNum, str, float, or int
|
|
207
|
+
:return: result
|
|
208
|
+
"""
|
|
209
|
+
if not isinstance(other, EngNumber):
|
|
210
|
+
other = EngUnit(str(other))
|
|
211
|
+
|
|
212
|
+
return EngUnit(str(other.eng_num / self.eng_num)
|
|
213
|
+
+ (other.unit + '/' + self.unit))
|
|
214
|
+
|
|
215
|
+
def __lt__(self, other):
|
|
216
|
+
"""
|
|
217
|
+
Compare two engineering numbers, with units
|
|
218
|
+
:param other: EngNum, str, float, or int
|
|
219
|
+
:return: result
|
|
220
|
+
"""
|
|
221
|
+
if not isinstance(other, EngNumber):
|
|
222
|
+
other = EngUnit(str(other))
|
|
223
|
+
|
|
224
|
+
if self.unit != other.unit:
|
|
225
|
+
raise AttributeError('units do not match')
|
|
226
|
+
|
|
227
|
+
return self.eng_num < other.eng_num
|
|
228
|
+
|
|
229
|
+
def __gt__(self, other):
|
|
230
|
+
"""
|
|
231
|
+
Compare two engineering numbers, with units
|
|
232
|
+
:param other: EngNum, str, float, or int
|
|
233
|
+
:return: result
|
|
234
|
+
"""
|
|
235
|
+
if not isinstance(other, EngNumber):
|
|
236
|
+
other = EngUnit(str(other))
|
|
237
|
+
|
|
238
|
+
if self.unit != other.unit:
|
|
239
|
+
raise AttributeError('units do not match')
|
|
240
|
+
|
|
241
|
+
return self.eng_num > other.eng_num
|
|
242
|
+
|
|
243
|
+
def __le__(self, other):
|
|
244
|
+
"""
|
|
245
|
+
Compare two engineering numbers, with units
|
|
246
|
+
:param other: EngNum, str, float, or int
|
|
247
|
+
:return: result
|
|
248
|
+
"""
|
|
249
|
+
if not isinstance(other, EngNumber):
|
|
250
|
+
other = EngUnit(str(other))
|
|
251
|
+
|
|
252
|
+
if self.unit != other.unit:
|
|
253
|
+
raise AttributeError('units do not match')
|
|
254
|
+
|
|
255
|
+
return self.eng_num <= other.eng_num
|
|
256
|
+
|
|
257
|
+
def __ge__(self, other):
|
|
258
|
+
"""
|
|
259
|
+
Compare two engineering numbers, with units
|
|
260
|
+
:param other: EngNum, str, float, or int
|
|
261
|
+
:return: result
|
|
262
|
+
"""
|
|
263
|
+
if not isinstance(other, EngNumber):
|
|
264
|
+
other = EngUnit(str(other))
|
|
265
|
+
|
|
266
|
+
if self.unit != other.unit:
|
|
267
|
+
raise AttributeError('units do not match')
|
|
268
|
+
|
|
269
|
+
return self.eng_num >= other.eng_num
|
|
270
|
+
|
|
271
|
+
def __eq__(self, other):
|
|
272
|
+
"""
|
|
273
|
+
Compare two engineering numbers, with units
|
|
274
|
+
:param other: EngNum, str, float, or int
|
|
275
|
+
:return: result
|
|
276
|
+
"""
|
|
277
|
+
if not isinstance(other, (EngNumber, EngUnit, str, int, float)):
|
|
278
|
+
return NotImplemented
|
|
279
|
+
if not isinstance(other, EngNumber):
|
|
280
|
+
other = EngUnit(str(other))
|
|
281
|
+
|
|
282
|
+
if self.unit != other.unit:
|
|
283
|
+
raise AttributeError('units do not match')
|
|
284
|
+
|
|
285
|
+
return self.eng_num == other.eng_num
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
class EngNumber:
|
|
289
|
+
"""
|
|
290
|
+
Used for easy manipulation of numbers which use engineering notation
|
|
291
|
+
"""
|
|
292
|
+
|
|
293
|
+
def __init__(self, value,
|
|
294
|
+
precision=2, significant=0, separator=""):
|
|
295
|
+
"""
|
|
296
|
+
Initialize the class
|
|
297
|
+
|
|
298
|
+
:param value: string, integer, or float representing
|
|
299
|
+
the numeric value of the number
|
|
300
|
+
:param precision: the precision past the decimal - default to 2
|
|
301
|
+
:param significant: the number of significant digits
|
|
302
|
+
if given, significant takes precendence over precision
|
|
303
|
+
"""
|
|
304
|
+
self.precision = precision
|
|
305
|
+
self.significant = significant
|
|
306
|
+
self.separator = separator
|
|
307
|
+
|
|
308
|
+
if isinstance(value, str):
|
|
309
|
+
suffix_keys = [key for key in _suffix_lookup.keys() if key != '']
|
|
310
|
+
|
|
311
|
+
for suffix in suffix_keys:
|
|
312
|
+
if suffix == value[-1]:
|
|
313
|
+
value = value[:-1] + _suffix_lookup[suffix]
|
|
314
|
+
break
|
|
315
|
+
|
|
316
|
+
self.number = Decimal(value)
|
|
317
|
+
|
|
318
|
+
elif (isinstance(value, int)
|
|
319
|
+
or isinstance(value, float)
|
|
320
|
+
or isinstance(value, EngNumber)):
|
|
321
|
+
self.number = Decimal(str(value))
|
|
322
|
+
else:
|
|
323
|
+
# finally, check for numpy import
|
|
324
|
+
if 'numpy' in sys.modules and isinstance(value, numpy.integer):
|
|
325
|
+
self.number = Decimal(str(value))
|
|
326
|
+
|
|
327
|
+
def to_pn(self, sub_letter=None):
|
|
328
|
+
"""
|
|
329
|
+
Returns the part number equivalent. For instance,
|
|
330
|
+
a '1k' would still be '1k', but a
|
|
331
|
+
'1.2k' would, instead, be a '1k2'
|
|
332
|
+
:return:
|
|
333
|
+
"""
|
|
334
|
+
string = str(self)
|
|
335
|
+
if '.' not in string:
|
|
336
|
+
return string
|
|
337
|
+
|
|
338
|
+
# take care of the case of when there is no scaling unit
|
|
339
|
+
if not string[-1].isalpha():
|
|
340
|
+
if sub_letter is not None:
|
|
341
|
+
return string.replace('.', sub_letter)
|
|
342
|
+
|
|
343
|
+
return string
|
|
344
|
+
|
|
345
|
+
letter = string[-1]
|
|
346
|
+
return string.replace('.', letter)[:-1].strip(self.separator)
|
|
347
|
+
|
|
348
|
+
def __repr__(self):
|
|
349
|
+
"""
|
|
350
|
+
Returns the string representation
|
|
351
|
+
:return: a string representing the engineering number
|
|
352
|
+
"""
|
|
353
|
+
# since Decimal class only really converts number that are very small
|
|
354
|
+
# into engineering notation, then we will simply make all number a
|
|
355
|
+
# small number and take advantage of Decimal class
|
|
356
|
+
num_str = self.number * Decimal('10e-31')
|
|
357
|
+
num_str = num_str.to_eng_string().lower()
|
|
358
|
+
|
|
359
|
+
base, exponent = num_str.split('e')
|
|
360
|
+
|
|
361
|
+
if self.significant > 0:
|
|
362
|
+
if abs(Decimal(base)) >= 100.0:
|
|
363
|
+
base = str(round(Decimal(base), self.significant - 3))
|
|
364
|
+
elif abs(Decimal(base)) >= 10.0:
|
|
365
|
+
base = str(round(Decimal(base), self.significant - 2))
|
|
366
|
+
else:
|
|
367
|
+
base = str(round(Decimal(base), self.significant - 1))
|
|
368
|
+
else:
|
|
369
|
+
base = str(round(Decimal(base), self.precision))
|
|
370
|
+
|
|
371
|
+
if 'e' in base.lower():
|
|
372
|
+
base = str(int(Decimal(base)))
|
|
373
|
+
|
|
374
|
+
# remove trailing decimals:
|
|
375
|
+
# print(base)
|
|
376
|
+
# https://stackoverflow.com/questions/3410976/how-to-round-a-number-to-significant-figures-in-python
|
|
377
|
+
# https://stackoverflow.com/questions/11227620/drop-trailing-zeros-from-decimal
|
|
378
|
+
# base = '%s' % float("%#.2G"%Decimal(base))
|
|
379
|
+
# print(base)
|
|
380
|
+
# remove trailing decimal
|
|
381
|
+
if '.' in base:
|
|
382
|
+
base = base.rstrip('.')
|
|
383
|
+
|
|
384
|
+
# remove trailing .00 in precision 2
|
|
385
|
+
if self.precision == 2 and self.significant == 0:
|
|
386
|
+
if '.00' in base:
|
|
387
|
+
base = base[:-3]
|
|
388
|
+
|
|
389
|
+
return base + self.separator + _exponent_lookup_scaled[exponent]
|
|
390
|
+
|
|
391
|
+
def __str__(self, eng=True, context=None):
|
|
392
|
+
"""
|
|
393
|
+
Returns the string representation
|
|
394
|
+
:return: a string representing the engineering number
|
|
395
|
+
"""
|
|
396
|
+
return self.__repr__()
|
|
397
|
+
|
|
398
|
+
def __int__(self):
|
|
399
|
+
"""
|
|
400
|
+
Implements the 'int()' method
|
|
401
|
+
:return:
|
|
402
|
+
"""
|
|
403
|
+
return int(self.number)
|
|
404
|
+
|
|
405
|
+
def __float__(self):
|
|
406
|
+
"""
|
|
407
|
+
Implements the 'float()' method
|
|
408
|
+
:return:
|
|
409
|
+
"""
|
|
410
|
+
return float(self.number)
|
|
411
|
+
|
|
412
|
+
def __add__(self, other):
|
|
413
|
+
"""
|
|
414
|
+
Add two engineering numbers
|
|
415
|
+
:param other: EngNum, str, float, or int
|
|
416
|
+
:return: result
|
|
417
|
+
"""
|
|
418
|
+
if not isinstance(other, EngNumber):
|
|
419
|
+
other = EngNumber(other)
|
|
420
|
+
|
|
421
|
+
num = self.number + other.number
|
|
422
|
+
return EngNumber(str(num))
|
|
423
|
+
|
|
424
|
+
def __radd__(self, other):
|
|
425
|
+
"""
|
|
426
|
+
Add two engineering numbers
|
|
427
|
+
:param other: EngNum, str, float, or int
|
|
428
|
+
:return: result
|
|
429
|
+
"""
|
|
430
|
+
return self.__add__(other)
|
|
431
|
+
|
|
432
|
+
def __sub__(self, other):
|
|
433
|
+
"""
|
|
434
|
+
Subtract two engineering numbers
|
|
435
|
+
:param other: EngNum, str, float, or int
|
|
436
|
+
:return: result
|
|
437
|
+
"""
|
|
438
|
+
if not isinstance(other, EngNumber):
|
|
439
|
+
other = EngNumber(other)
|
|
440
|
+
|
|
441
|
+
num = self.number - other.number
|
|
442
|
+
return EngNumber(str(num))
|
|
443
|
+
|
|
444
|
+
def __rsub__(self, other):
|
|
445
|
+
"""
|
|
446
|
+
Subtract two engineering numbers
|
|
447
|
+
:param other: EngNum, str, float, or int
|
|
448
|
+
:return: result
|
|
449
|
+
"""
|
|
450
|
+
if not isinstance(other, EngNumber):
|
|
451
|
+
other = EngNumber(other)
|
|
452
|
+
|
|
453
|
+
num = other.number - self.number
|
|
454
|
+
return EngNumber(str(num))
|
|
455
|
+
|
|
456
|
+
def __mul__(self, other):
|
|
457
|
+
"""
|
|
458
|
+
Multiply two engineering numbers
|
|
459
|
+
:param other: EngNum, str, float, or int
|
|
460
|
+
:return: result
|
|
461
|
+
"""
|
|
462
|
+
if not isinstance(other, EngNumber):
|
|
463
|
+
other = EngNumber(other)
|
|
464
|
+
|
|
465
|
+
num = self.number * other.number
|
|
466
|
+
return EngNumber(str(num))
|
|
467
|
+
|
|
468
|
+
def __rmul__(self, other):
|
|
469
|
+
"""
|
|
470
|
+
Multiply two engineering numbers
|
|
471
|
+
:param other: EngNum, str, float, or int
|
|
472
|
+
:return: result
|
|
473
|
+
"""
|
|
474
|
+
return self.__mul__(other)
|
|
475
|
+
|
|
476
|
+
def __truediv__(self, other):
|
|
477
|
+
"""
|
|
478
|
+
Divide two engineering numbers
|
|
479
|
+
:param other: EngNum, str, float, or int
|
|
480
|
+
:return: result
|
|
481
|
+
"""
|
|
482
|
+
if not isinstance(other, EngNumber):
|
|
483
|
+
other = EngNumber(other)
|
|
484
|
+
|
|
485
|
+
num = self.number / other.number
|
|
486
|
+
return EngNumber(str(num))
|
|
487
|
+
|
|
488
|
+
def __rtruediv__(self, other):
|
|
489
|
+
"""
|
|
490
|
+
Divide two engineering numbers
|
|
491
|
+
:param other: EngNum, str, float, or int
|
|
492
|
+
:return: result
|
|
493
|
+
"""
|
|
494
|
+
if not isinstance(other, EngNumber):
|
|
495
|
+
other = EngNumber(other)
|
|
496
|
+
|
|
497
|
+
num = other.number / self.number
|
|
498
|
+
return EngNumber(str(num))
|
|
499
|
+
|
|
500
|
+
def __lt__(self, other):
|
|
501
|
+
"""
|
|
502
|
+
Compare two engineering numbers
|
|
503
|
+
:param other: EngNum, str, float, or int
|
|
504
|
+
:return: result
|
|
505
|
+
"""
|
|
506
|
+
if not isinstance(other, EngNumber):
|
|
507
|
+
other = EngNumber(other)
|
|
508
|
+
|
|
509
|
+
return self.number < other.number
|
|
510
|
+
|
|
511
|
+
def __gt__(self, other):
|
|
512
|
+
"""
|
|
513
|
+
Compare two engineering numbers
|
|
514
|
+
:param other: EngNum, str, float, or int
|
|
515
|
+
:return: result
|
|
516
|
+
"""
|
|
517
|
+
if not isinstance(other, EngNumber):
|
|
518
|
+
other = EngNumber(other)
|
|
519
|
+
|
|
520
|
+
return self.number > other.number
|
|
521
|
+
|
|
522
|
+
def __le__(self, other):
|
|
523
|
+
"""
|
|
524
|
+
Compare two engineering numbers
|
|
525
|
+
:param other: EngNum, str, float, or int
|
|
526
|
+
:return: result
|
|
527
|
+
"""
|
|
528
|
+
if not isinstance(other, EngNumber):
|
|
529
|
+
other = EngNumber(other)
|
|
530
|
+
|
|
531
|
+
return self.number <= other.number
|
|
532
|
+
|
|
533
|
+
def __ge__(self, other):
|
|
534
|
+
"""
|
|
535
|
+
Compare two engineering numbers
|
|
536
|
+
:param other: EngNum, str, float, or int
|
|
537
|
+
:return: result
|
|
538
|
+
"""
|
|
539
|
+
if not isinstance(other, EngNumber):
|
|
540
|
+
other = EngNumber(other)
|
|
541
|
+
|
|
542
|
+
return self.number >= other.number
|
|
543
|
+
|
|
544
|
+
def __eq__(self, other):
|
|
545
|
+
"""
|
|
546
|
+
Compare two engineering numbers
|
|
547
|
+
:param other: EngNum, str, float, or int
|
|
548
|
+
:return: result
|
|
549
|
+
"""
|
|
550
|
+
if not isinstance(other, (EngNumber, str, int, float)):
|
|
551
|
+
return NotImplemented
|
|
552
|
+
if not isinstance(other, EngNumber):
|
|
553
|
+
other = EngNumber(other)
|
|
554
|
+
|
|
555
|
+
return self.number == other.number
|