Convert float number to string with engineering notation (with SI prefix) in Python

后端 未结 5 1505
离开以前
离开以前 2021-01-12 20:16

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

相关标签:
5条回答
  • 2021-01-12 20:32

    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
    
    0 讨论(0)
  • 2021-01-12 20:33

    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
    
    0 讨论(0)
  • 2021-01-12 20:34

    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
    
    0 讨论(0)
  • 2021-01-12 20:39

    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
    
    
    0 讨论(0)
  • 2021-01-12 20:49

    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.

    0 讨论(0)
提交回复
热议问题