Search code examples
pythonprintingscientific-notationstring.format

Print in scientific format with powers of ten being only multiples of 3


I haven't found a way to only get exponents which are multiples of 3, when displaying numbers in the scientific format. Neither did I succeed writing a simple custom formatting function.

Here is a quick example:
Normal behaviour using scientific notation with pythons .format():

numbers = [1.2e-2, 1.3e-3, 1.5e5, 1.6e6]

for n in numbers:
    print("{:.E}".format(n))
>>> 1.20E-02  
    1.30E-03  
    1.50E+05  
    1.60E+06  

I, however, need the following output:

>>> 12.00E-03   
     1.30E-03   
    15.00E+06  
     1.60E+06  

Does anyone know a convenient way for me to get the desired formatting?


Solution

  • Well, it depends on if you want the output format to always adjust to the nearest power of 3, or if you want it to adjust to the nearest lower power of 3. Basically it comes to: how you handle 1.50E+05? Should it be 150.00E+03 or 0.15E+06?

    Case 1: nearest lower power of 3

    from math import log10,floor
    
    numbers = [1.2e-2, 1.3e-3, 1.5e5, 1.6e6]
        
        
    def adjusted_scientific_notation(val,num_decimals=2,exponent_pad=2):
        exponent_template = "{:0>%d}" % exponent_pad
        mantissa_template = "{:.%df}" % num_decimals
        
        order_of_magnitude = floor(log10(abs(val)))
        nearest_lower_third = 3*(order_of_magnitude//3)
        adjusted_mantissa = val*10**(-nearest_lower_third)
        adjusted_mantissa_string = mantissa_template.format(adjusted_mantissa)
        adjusted_exponent_string = "+-"[nearest_lower_third<0] + exponent_template.format(abs(nearest_lower_third))
        return adjusted_mantissa_string+"E"+adjusted_exponent_string
    
    for n in numbers:
        print("{0:.2E} -> {1: >10}".format(n,adjusted_scientific_notation(n)))
    

    which prints out:

    1.20E-02 ->  12.00E-03
    1.30E-03 ->   1.30E-03
    1.50E+05 -> 150.00E+03
    1.60E+06 ->   1.60E+06
    

    Case 2: nearest power of 3

    def adjusted_scientific_notation(val,num_decimals=2,exponent_pad=2):
        exponent_template = "{:0>%d}" % exponent_pad
        mantissa_template = "{:.%df}" % num_decimals
        
        order_of_magnitude = floor(log10(abs(val)))
        nearest_third = 3*(order_of_magnitude//3+int(order_of_magnitude%3==2))
        adjusted_mantissa = val*10**(-nearest_third)
        adjusted_mantissa_string = mantissa_template.format(adjusted_mantissa)
        adjusted_exponent_string = "+-"[nearest_third<0] + exponent_template.format(abs(nearest_third))
        return adjusted_mantissa_string+"E"+adjusted_exponent_string
    
    for n in numbers:
        print("{0:.2E} -> {1: >10}".format(n,adjusted_scientific_notation(n)))
    

    which prints out:

    1.20E-02 ->  12.00E-03
    1.30E-03 ->   1.30E-03
    1.50E+05 ->   0.15E+06
    1.60E+06 ->   1.60E+06