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

Question:

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?

Asked By: NewNewton

||

Answers:

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