I have a float number such as x=23392342.1
I would like to convert it to a string with engineering notation (with metric prefix)
http://en.wikip
Use the QuantiPhy package. It is a stable well documented and well supported package that is designed to do just what you want.
>>> from quantiphy import Quantity
>>> v = Quantity(23.3923421E6)
>>> str(v)
'23.392M'
>>> v.render(prec='full')
'23.3923421M'
Generally people use SI unit prefixes with units, and Quantity is designed to combine the units with the number.
>>> v = Quantity(23.3923421E6, 'V')
>>> print(v)
23.392 MV
>>> f = Quantity('23.3923421 MHz')
>>> print('{}'.format(f))
23.392 MHz
Quantity subclasses float, so you can use quantities in expressions as you would a float:
>>> t = 1/f
>>> print(t)
4.274903281275114e-08
>>> t = Quantity(t, 's')
>>> print(t)
42.749 ns
This is a simple method with no dependencies:
def to_units(x_):
units = {-12: "T",-9: "G",-6: "M",-3: "K",0: "",3: "m",6: "µ",9: "n",12: "p",15: "f"}
k = -12
while x_ * 10.0**k < 1:
k += 3
return f"{x_*10.0**k}{units[k]}"
Example:
for i in range(-15,15):
print(f"{to_units(1*10.0**i)} \t {1*10.0**i:1,.15f}")
1.0f 0.000000000000001
10.0f 0.000000000000010
100.0f 0.000000000000100
1.0p 0.000000000001000
10.0p 0.000000000010000
100.0p 0.000000000100000
1.0n 0.000000001000000
10.0n 0.000000010000000
100.0n 0.000000100000000
1.0µ 0.000001000000000
10.0µ 0.000010000000000
100.0µ 0.000100000000000
1.0m 0.001000000000000
10.0m 0.010000000000000
100.0m 0.100000000000000
1.0 1.000000000000000
10.0 10.000000000000000
100.0 100.000000000000000
1.0K 1,000.000000000000000
10.0K 10,000.000000000000000
100.0K 100,000.000000000000000
1.0M 1,000,000.000000000000000
10.0M 10,000,000.000000000000000
100.0M 100,000,000.000000000000000
1.0G 1,000,000,000.000000000000000
10.0G 10,000,000,000.000000000000000
100.0G 100,000,000,000.000000000000000
1.0T 1,000,000,000,000.000000000000000
10.0T 10,000,000,000,000.000000000000000
100.0T 100,000,000,000,000.000000000000000
Here is a function inspired from Formatting a number with a metric prefix?
metric.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import math
def to_si(d, sep=' '):
"""
Convert number to string with SI prefix
:Example:
>>> to_si(2500.0)
'2.5 k'
>>> to_si(2.3E6)
'2.3 M'
>>> to_si(2.3E-6)
'2.3 µ'
>>> to_si(-2500.0)
'-2.5 k'
>>> to_si(0)
'0'
"""
inc_prefixes = ['k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y']
dec_prefixes = ['m', 'µ', 'n', 'p', 'f', 'a', 'z', 'y']
if d == 0:
return str(0)
degree = int(math.floor(math.log10(math.fabs(d)) / 3))
prefix = ''
if degree != 0:
ds = degree / math.fabs(degree)
if ds == 1:
if degree - 1 < len(inc_prefixes):
prefix = inc_prefixes[degree - 1]
else:
prefix = inc_prefixes[-1]
degree = len(inc_prefixes)
elif ds == -1:
if -degree - 1 < len(dec_prefixes):
prefix = dec_prefixes[-degree - 1]
else:
prefix = dec_prefixes[-1]
degree = -len(dec_prefixes)
scaled = float(d * math.pow(1000, -degree))
s = "{scaled}{sep}{prefix}".format(scaled=scaled,
sep=sep,
prefix=prefix)
else:
s = "{d}".format(d=d)
return s
if __name__ == "__main__":
import doctest
doctest.testmod()
and its usage:
from metric import to_si
d = 23392342.1
print(to_si(d))
It will display
23.3923421 M
You can use Prefixed which has a float type with additional formatting options.
>>> from prefixed import Float
>>> x = Float(23392342.1)
>>> print(f'{x:!h}')
23.392342 M
Or if you want to keep 7 decimal places
>>> print(f'{x:!.7h}')
23.3923421 M
A direct solution is to use the Decimal.to_eng_string method and then do a dictionary lookup to convert the exponent to appropriate metric prefix.