Вопрос-Ответ

Formatting floats without trailing zeros

Форматирование с плавающей точкой без завершающих нулей

Как я могу отформатировать число с плавающей запятой так, чтобы оно не содержало завершающих нулей? Другими словами, я хочу, чтобы результирующая строка была как можно короче.

Например:

3 -> "3"
3. -> "3"
3.0 -> "3"
3.1 -> "3.1"
3.14 -> "3.14"
3.140 -> "3.14"
Переведено автоматически
Ответ 1

Вы могли бы использовать %g для достижения этой цели:

'%g'%(3.140)

или, с Python ≥ 2.6:

'{0:g}'.format(3.140)

или, с Python ≥ 3.6:

f'{3.140:g}'

Из документации по format: g причинам (среди прочего)


незначительные конечные нули [должны быть] удалены из значения, и десятичная точка также удаляется, если после нее не осталось цифр.


Ответ 2

Я бы сделал ('%f' % x).rstrip('0').rstrip('.') - гарантирует форматирование с фиксированной запятой, а не научную нотацию и т.д. и т.п. Да, не так гладко и элегантно, как %g, но это работает (и я не знаю, как заставить %g никогда не использовать научную нотацию;-).

Ответ 3

После просмотра ответов на несколько похожих вопросов это кажется мне лучшим решением:

def floatToString(inputValue):
return ('%.15f' % inputValue).rstrip('0').rstrip('.')

Мои рассуждения:

%g не избавляет от научной нотации.

>>> '%g' % 0.000035
'3.5e-05'

15 знаков после запятой, кажется, позволяют избежать странного поведения и обладают достаточной точностью для моих нужд.

>>> ('%.15f' % 1.35).rstrip('0').rstrip('.')
'1.35'
>>> ('%.16f' % 1.35).rstrip('0').rstrip('.')
'1.3500000000000001'

Я мог бы использовать format(inputValue, '.15f'). вместо '%.15f' % inputValue, но это немного медленнее (~ 30%).

Я мог бы использовать Decimal(inputValue).normalize(), но у этого также есть несколько проблем. Во-первых, это НАМНОГО медленнее (~ 11 раз). Я также обнаружил, что, хотя он обладает довольно высокой точностью, он по-прежнему страдает от потери точности при использовании normalize().

>>> Decimal('0.21000000000000000000000000006').normalize()
Decimal('0.2100000000000000000000000001')
>>> Decimal('0.21000000000000000000000000006')
Decimal('0.21000000000000000000000000006')

Самое главное, я бы все равно преобразовывал в Decimal из a float, что может привести к получению чего-то другого, кроме числа, которое вы туда ввели. Я думаю, Decimal работает лучше всего, когда арифметика остается в Decimal и Decimal инициализируется строкой.

>>> Decimal(1.35)
Decimal('1.350000000000000088817841970012523233890533447265625')
>>> Decimal('1.35')
Decimal('1.35')

Я уверен, что проблема точности Decimal.normalize() может быть скорректирована в соответствии с тем, что необходимо, с помощью настроек контекста, но, учитывая и без того низкую скорость и отсутствие необходимости в смехотворной точности, а также тот факт, что я все равно буду преобразовывать из числа с плавающей точкой и все равно потеряю точность, я не думал, что это того стоит.

Меня не беспокоит возможный результат "-0", поскольку -0.0 - это допустимое число с плавающей запятой, и, вероятно, это все равно было бы редким явлением, но поскольку вы упомянули, что хотите сохранить результат строки как можно короче, вы всегда можете использовать дополнительное условие с очень небольшими дополнительными затратами на скорость.

def floatToString(inputValue):
result = ('%.15f' % inputValue).rstrip('0').rstrip('.')
return '0' if result == '-0' else result
Ответ 4

Как насчет того, чтобы попробовать самый простой и, вероятно, наиболее эффективный подход? Метод normalize() удаляет все крайние правые конечные нули.

from decimal import Decimal

print (Decimal('0.001000').normalize())
# Result: 0.001

Работает в Python 2 и Python 3.

-- Обновлено --

Единственная проблема, как указал @BobStein-VisiBone, заключается в том, что такие числа, как 10, 100, 1000... будут отображаться в экспоненциальном представлении. Это можно легко исправить, используя вместо этого следующую функцию:

from decimal import Decimal


def format_float(f):
d = Decimal(str(f));
return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize()
python