Python Library To Convert Between Si Unit Prefixes
Solution 1:
I ported a simple function (original C version written by Jukka “Yucca” Korpela) to Python for formatting numbers according to SI standards. I use it often, for example, to set tick labels on plots, etc.
You can install it with:
pip install si-prefix
The source is available on GitHub.
Example usage:
from si_prefix import si_format
print si_format(.5)
# 500.0m (default precision is 1)print si_format(.01331, precision=2)
# 13.31mprint si_format(1331, precision=2)
# 1.33kprint si_format(1331, precision=0)
# 1k
Solution 2:
Dictionaries
If you don't want to use any 3rd-party library like the ones listed below, you can actually implement your own parsing function.
Use a dictionary to match up the prefixes to their values. I've done it for you already:
_prefix = {'y': 1e-24, # yocto'z': 1e-21, # zepto'a': 1e-18, # atto'f': 1e-15, # femto'p': 1e-12, # pico'n': 1e-9, # nano'u': 1e-6, # micro'm': 1e-3, # mili'c': 1e-2, # centi'd': 1e-1, # deci'k': 1e3, # kilo'M': 1e6, # mega'G': 1e9, # giga'T': 1e12, # tera'P': 1e15, # peta'E': 1e18, # exa'Z': 1e21, # zetta'Y': 1e24, # yotta
}
Then you can use regex (as described by my answer here) to search or parse the input and use the dictionary for getting the appropriate value.
Unum
Unum is well finished and thoroughly documented library.
Pros:
- allows you to define arbitrary units (magnitude only supports user-defined units as long as they are a combination of the base units).
Cons:
- doesn't handle prefixes well
- clutters your namespace with all its unit definitions (you end up with variables named
M
,S
etc. in your namespace)
Magnitude
You can also use Magnitude, another library. It supports all the kinds of SI unit prefixes you're talking about, plus it'll handle the parsing as well. From the site:
A physical quantity is a number with a unit, like 10 km/h. Units are specified as strings. They can be any of the SI units, plus a bunch of non-SI, bits, dollars, and any combination of them. They can include the standard SI prefixes. ... All standard prefixes are understood, from yocto to yotta and from kibi to exbi.
Solution 3:
QuantiPhy is a new package that converts to and from numbers with SI scale factors. It is often a better choice that the unit packages such as Unum and Magnitude that are heavier and focused on the units rather than the scale factors.
QuantiPhy provides Quantity, which is an object that combines a number with its unit of measure (the units are optional). When creating a quantity you can use SI unit prefixes. Once you have a Quantity you can use it in expressions, where it acts as a float. Or you can convert it to a string, in which case it uses the SI unit prefixes by default.
>>> from quantiphy import Quantity
# convert strings to quantities>>> duration = Quantity('0.12 ks')
>>> print(duration)
120 s
# convert to other units when rendering to a string>>> print(duration.render(scale='min'))
2min# quantities act like floats in expressions>>> rate = 1/duration
>>> print(rate)
0.008333333333333333# convert floats to quantities>>> rate = Quantity(rate, 'Hz')
>>> print(rate)
8.3333 mHz
# can be used in format strings>>> print(f'Duration = {duration:<12.3} Rate = {rate}')
Duration = 120 s Rate = 8.3333 mHz
By default QuantiPhy uses the natural prefix when rendering to a string, which is probably what you want. But you can force it to render to a specific prefix using scaling:
>>>mass = Quantity('1000 g')>>>print(mass)
1 kg
>>>print(mass.render(show_si=False))
1e3 g
>>>print(mass.render(show_si=False, scale=(1e-12, 'pg')))
1e9 pg
In this case you must turn off SI unit prefixes to avoid getting multiple prefixes: '1 npg'.
A more natural example might be where you are converting units:
>>>l = Quantity('2um') >>>print(l.render(scale='Å'))
20 kÅ
>>>print(f'{l:sÅ}')
20 kÅ
The last example shows that you can place your desired units in the format string after the type and the conversion will be done for you automatically.
Solution 4:
I don't know if this is the best answer but it is working in my case. Feel free to verify my solution. I am working for first time with Python and constructive criticism is welcome... along with positive feedback :D This is my code:
classUnits:
def__init__(self):
global si;
si = {
-18 : {'multiplier' : 10 ** 18, 'prefix' : 'a'},
-17 : {'multiplier' : 10 ** 18, 'prefix' : 'a'},
-16 : {'multiplier' : 10 ** 18, 'prefix' : 'a'},
-15 : {'multiplier' : 10 ** 15, 'prefix' : 'f'},
-14 : {'multiplier' : 10 ** 15, 'prefix' : 'f'},
-13 : {'multiplier' : 10 ** 15, 'prefix' : 'f'},
-12 : {'multiplier' : 10 ** 12, 'prefix' : 'p'},
-11 : {'multiplier' : 10 ** 12, 'prefix' : 'p'},
-10 : {'multiplier' : 10 ** 12, 'prefix' : 'p'},
-9 : {'multiplier' : 10 ** 9, 'prefix' : 'n'},
-8 : {'multiplier' : 10 ** 9, 'prefix' : 'n'},
-7 : {'multiplier' : 10 ** 9, 'prefix' : 'n'},
-6 : {'multiplier' : 10 ** 6, 'prefix' : 'u'},
-5 : {'multiplier' : 10 ** 6, 'prefix' : 'u'},
-4 : {'multiplier' : 10 ** 6, 'prefix' : 'u'},
-3 : {'multiplier' : 10 ** 3, 'prefix' : 'm'},
-2 : {'multiplier' : 10 ** 2, 'prefix' : 'c'},
-1 : {'multiplier' : 10 ** 1, 'prefix' : 'd'},
0 : {'multiplier' : 1, 'prefix' : ''},
1 : {'multiplier' : 10 ** 1, 'prefix' : 'da'},
2 : {'multiplier' : 10 ** 3, 'prefix' : 'k'},
3 : {'multiplier' : 10 ** 3, 'prefix' : 'k'},
4 : {'multiplier' : 10 ** 3, 'prefix' : 'k'},
5 : {'multiplier' : 10 ** 3, 'prefix' : 'k'},
6 : {'multiplier' : 10 ** 6, 'prefix' : 'M'},
7 : {'multiplier' : 10 ** 6, 'prefix' : 'M'},
8 : {'multiplier' : 10 ** 6, 'prefix' : 'M'},
9 : {'multiplier' : 10 ** 9, 'prefix' : 'G'},
10 : {'multiplier' : 10 ** 9, 'prefix' : 'G'},
11 : {'multiplier' : 10 ** 9, 'prefix' : 'G'},
12 : {'multiplier' : 10 ** 12, 'prefix' : 'T'},
13 : {'multiplier' : 10 ** 12, 'prefix' : 'T'},
14 : {'multiplier' : 10 ** 12, 'prefix' : 'T'},
15 : {'multiplier' : 10 ** 15, 'prefix' : 'P'},
16 : {'multiplier' : 10 ** 15, 'prefix' : 'P'},
17 : {'multiplier' : 10 ** 15, 'prefix' : 'P'},
18 : {'multiplier' : 10 ** 18, 'prefix' : 'E'},
}
defconvert(self, number):
# Checking if its negative or positiveif number < 0:
negative = True;
else:
negative = False;
# if its negative converting to positive (math.log()....)if negative:
number = number - (number*2);
# Taking the exponent
exponent = int(math.log10(number));
# Checking if it was negative converting it back to negativeif negative:
number = number - (number*2);
# If the exponent is smaler than 0 dividing the exponent with -1if exponent < 0:
exponent = exponent-1;
return [number * si[exponent]['multiplier'], si[exponent]['prefix']];
# If the exponent bigger than 0 just return itelif exponent > 0:
return [number / si[exponent]['multiplier'], si[exponent]['prefix']];
# If the exponent is 0 than return only the valueelif exponent == 0:
return [number, ''];
And this is how it works:
c1 = +1.189404E-010
fres = -4.07237500000000E+007;
ls = +1.943596E-005;
units = sci.Units();
rValue, rPrefix = units.convert(c1);
print rValue;
print rPrefix;
print units.convert(fres);
print units.convert(ls);
And the response is:
118.9404p[-40.72375, 'M'][19.435959999999998, 'u']
I don't know if anyone will find this helpful or not. I hope you do. I've posted here so the people who want help to see it also to give them an idea maybe they can optimize it :)
Solution 5:
I know this is an old thread, but I'd just like to throw out a reference to a python library I wrote which handles all manner of prefix unit conversion handling
Here's the major feature list:
- Converting between SI and NIST prefix units (
kB
toGiB
) - Converting between units of the same type (SI to SI, or NIST to NIST)
- Automatic human-readable prefix selection (like in hurry.filesize https://pypi.python.org/pypi/hurry.filesize)
- Basic arithmetic operations (subtracting 42KiB from 50GiB)
- Rich comparison operations (
1024 Bytes == 1KiB
) - bitwise operations (
<<
,>>
,&
,|
,^
) - Reading a device's storage capacity (Linux/OS X support only)
- argparse https://docs.python.org/2/library/argparse.html integration as a custom type
- progressbar https://code.google.com/p/python-progressbar/ integration as a better file transfer speed widget
- String parsing
- Sorting
Post a Comment for "Python Library To Convert Between Si Unit Prefixes"