### Python庫在SI單元前綴之間進行轉換

#### [英]Python library to convert between SI unit prefixes

I'm looking for a python library which comes with support to convert numbers between various SI prefixes, for example, kilo to pico, nano to giga and so on.What would you recommend?

## 5 个解决方案

### #1

7

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.31m

print si_format(1331, precision=2)
# 1.33k

print si_format(1331, precision=0)
# 1k
``````

4

# 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.

Unum已完成並完整記錄了庫。

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)
• 使用其所有單元定義來混淆您的命名空間(最終在命名空間中使用名為M,S等的變量)

# 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.

### #3

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:

``````class Units:
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' : 'd'},
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'},
}

def convert(self, number):
# Checking if its negative or positive
if 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 negative
if negative:
number = number - (number*2);

# If the exponent is smaler than 0 dividing the exponent with -1
if exponent < 0:
exponent = exponent-1;
return [number * si[exponent]['multiplier'], si[exponent]['prefix']];
# If the exponent bigger than 0 just return it
elif exponent > 0:
return [number / si[exponent]['multiplier'], si[exponent]['prefix']];
# If the exponent is 0 than return only the value
elif 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.9404
p
[-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 :)

### #4

1

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` to `GiB`)
• 在SI和NIST前綴單位之間轉換(kB到GiB)

• Converting between units of the same type (SI to SI, or NIST to NIST)
• 在相同類型的單元之間轉換(SI到SI,或NIST到NIST)

• Automatic human-readable prefix selection (like in hurry.filesize https://pypi.python.org/pypi/hurry.filesize)
• 自動人類可讀的前綴選擇(如hurry.filesize https://pypi.python.org/pypi/hurry.filesize)

• Basic arithmetic operations (subtracting 42KiB from 50GiB)
• 基本算術運算(從50GiB減去42KiB)

• Rich comparison operations (`1024 Bytes == 1KiB`)
• 豐富的比較操作(1024字節== 1KiB)

• bitwise operations (`<<`, `>>`, `&`, `|`, `^`)
• 按位運算(<<,>>,&,|,^)

• Reading a device's storage capacity (Linux/OS X support only)
• 讀取設備的存儲容量(僅限Linux / OS X支持)

• argparse https://docs.python.org/2/library/argparse.html integration as a custom type
• argparse https://docs.python.org/2/library/argparse.html集成為自定義類型

• progressbar https://code.google.com/p/python-progressbar/ integration as a better file transfer speed widget

• String parsing
• Sorting

### #5

1

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是一個新的包,可以轉換為具有SI比例因子的數字。單位打包(例如Unum和Magnitude)通常是更好的選擇,它們更重,並且專注於單位而不是比例因子。

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.

QuantiPhy提供Quantity,這是一個將數字與其度量單位組合在一起的對象(單位是可選的)。創建數量時,您可以使用SI單位前綴。獲得數量后,您可以在表達式中使用它,它可以充當浮點數。或者您可以將其轉換為字符串,在這種情況下,它默認使用SI單位前綴。

``````>>> 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'))
2 min

# 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.