100 lines
2.7 KiB
Python
100 lines
2.7 KiB
Python
#!/usr/bin/env python3
|
|
|
|
import math
|
|
import re
|
|
import decimal
|
|
from typing import Set
|
|
|
|
si_table = {
|
|
-8: ("yocto", "y", "y", 10e-24),
|
|
-7: ("zepto", "z", "z", 10e-21),
|
|
-6: ("atto", "a", "a", 10e-18),
|
|
-5: ("femto", "f", "f", 10e-15),
|
|
-4: ("pico", "p", "p", 10e-12),
|
|
-3: ("nano", "n", "n", 10e-9),
|
|
-2: ("micro", "u", "μ", 10e-6),
|
|
-1: ("milli", "m", "m", 10e-3),
|
|
0: ("", "", "", 0),
|
|
1: ("kilo", "k", "k", 10e3),
|
|
2: ("mega", "M", "M", 10e6),
|
|
3: ("giga", "G", "G", 10e9),
|
|
4: ("tera", "T", "T", 10e12),
|
|
5: ("peta", "P", "P", 10e15),
|
|
6: ("exa", "E", "E", 10e18),
|
|
7: ("zetta", "Z", "Z", 10e21),
|
|
8: ("yotta", "Y", "Y", 10e24),
|
|
}
|
|
|
|
_si_letters_set: Set[str] = set()
|
|
for n in si_table:
|
|
_si_letters_set.add(si_table[n][1])
|
|
_si_letters_set.add(si_table[n][2])
|
|
|
|
si_letters = "".join(sorted(_si_letters_set))
|
|
|
|
|
|
def prefix_tuple(value, utf=True):
|
|
value = float(value)
|
|
ex = math.log(abs(value * 1.0000001), 10)
|
|
nex = math.floor(ex) // 3
|
|
nval = value / 10 ** (nex * 3)
|
|
if nex not in si_table:
|
|
raise ValueError("No suitable SI prefix found")
|
|
if utf == True:
|
|
px = si_table[nex][2]
|
|
else:
|
|
px = si_table[nex][1]
|
|
return (nval, px)
|
|
|
|
|
|
def prefix(value, utf=True, replace_separator=True):
|
|
v, px = prefix_tuple(value, utf)
|
|
if px == "":
|
|
return "{:1.2f}".format(v).rstrip("0").rstrip(".")
|
|
elif replace_separator == True:
|
|
s = "{:1.2f}".format(v).replace(".", px).rstrip("0").rstrip(".")
|
|
return s
|
|
else:
|
|
s = "{:1.2f}".format(v).rstrip("0").rstrip(".")
|
|
return s + " {:s}".format(px)
|
|
|
|
|
|
def power_by_prefix(string):
|
|
for v in si_table:
|
|
if string in si_table[v]:
|
|
return v
|
|
raise ValueError()
|
|
|
|
|
|
def decode_infix(string):
|
|
np = "^(([1-9][0-9]*)?[0-9](\.[0-9]+)?) ?([{:s}])?$".format(si_letters)
|
|
ni = "^(([1-9][0-9]*)?[0-9](([{:s}])[0-9]+)?)$".format(si_letters)
|
|
rp = re.match(np, string)
|
|
ri = re.match(ni, string)
|
|
if rp is not None:
|
|
if rp.groups()[3] is not None:
|
|
power = power_by_prefix(rp.groups()[3])
|
|
else:
|
|
power = 0
|
|
base = decimal.Decimal(rp.groups()[0])
|
|
return base * decimal.Decimal("10") ** (power * 3)
|
|
elif ri is not None:
|
|
base = decimal.Decimal(str(ri.groups()[0]).replace(ri.groups()[3], "."))
|
|
power = power_by_prefix(ri.groups()[3])
|
|
return base * decimal.Decimal("10") ** (power * 3)
|
|
else:
|
|
raise ValueError()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
print(prefix(1.5632e11))
|
|
print(prefix(12.32e-9))
|
|
print(prefix(47000))
|
|
print(prefix(4700))
|
|
print(prefix(470))
|
|
|
|
print(si_letters)
|
|
print(decode_infix("0.23"))
|
|
print(decode_infix("470M"))
|
|
print(prefix(float(decode_infix("0k23"))))
|