class EngineeringNumberConverter(): prefixes = [ ('y', 1e-24), ('z', 1e-21), ('a', 1e-18), ('f', 1e-15), ('p', 1e-12), ('n', 1e-9), ('u', 1e-6), ('m', 1e-3), # We skip centi and dezi because no one really uses these besides for length measurements ('', 1), # We also skip h for hekto ('k', 1e3), ('M', 1e6), ('G', 1e9), ('T', 1e12), ('P', 1e15), ('E', 1e18), ('Z', 1e21), ('Y', 1e24), ] it_prefixes = [ ('', 1), ('Ki', 1024), ('Mi', 1024*1024), ('Gi', 1024*1024*1024), ('Ti', 1024*1024*1024*1024) ] @classmethod def number_to_engineering(c, number, it_unit=False): """ Convert a number to engineering SI syntax with prefix. This function will return a tuple of (new_number, prefix) """ if it_unit: used_prefixes = c.it_prefixes else: used_prefixes = c.prefixes if (len(used_prefixes) < 2): return (number / used_prefixes[0][1], used_prefixes[0]) for i, (prefix, scale) in enumerate(used_prefixes[1:], 1): if number < scale: return (number / used_prefixes[i-1][1], used_prefixes[i-1][0]) return (number / used_prefixes[-1][1], used_prefixes[-1][0]) @classmethod def engineering_to_number(c, input): cleaned_input = input.strip().replace(' ', '') selected_scaling = 1 for (prefix, scale) in c.prefixes+c.it_prefixes: if prefix == '': continue if cleaned_input.endswith(prefix): cleaned_input = cleaned_input.replace(prefix, '') selected_scaling = scale break return float(cleaned_input) * selected_scaling