спецификатор формата g
обычно хорош, если вам нужна научная запись, то есть:
my_format = "{:.10g}".format
должен делать правильные вещи:
>>> list(my_format(v) for v in (0.0000000456, 12.345678987654321, 12345678987654321))
['4.56e-08', '12.34567899', '1.234567899e+16']
Позже я понял, что вышефункция не делает то, что хотел ОП
Основываясь на полезных комментариях @a_guest, я пришел к следующему:
def my_format(v, length=10):
n = length
while n > 0:
i = len('%#.*g' % (n, v))
s = '%.*g' % (n + n - i, v)
if len(s) <= length:
return s
n -= 1
return s
Теперь я получаю ['4.56e-08', '12.345679', '1.2346e+16']
назад, что ближек тому, что было нужно.
Я проверил это, сгенерировав много случайных чисел, используя:
from random import uniform
def rnd_float():
return uniform(-10, 10) * 10 ** (uniform(-1.6, 1.6) ** 11)
довольно произвольно, но генерирует числа, достаточно близкие к тому распределению, которое мне небезразлично.Т.е. в основном около 1, но некоторые очень маленькие и большие с приличной вероятностью.
Я передал числа от этого до my_format
100k раз и получаю обратно соответственно отформатированные числа.