Форматирование плавает в Python без лишних нулей
Как отформатировать поплавок, чтобы он не содержал нулей remaing? Другими словами, Я хочу, чтобы результирующая строка была как можно короче..?
Как:
3 -> "3"
3. -> "3"
3.0 -> "3"
3.1 -> "3.1"
3.14 -> "3.14"
3.140 -> "3.14"
14 ответов:
меня, я бы сделал
('%f' % x).rstrip('0').rstrip('.')-- гарантирует форматирование с фиксированной точкой, а не научную нотацию и т. д. Да, не так гладко и элегантно, как%g, но он работает (и я не знаю, как заставить%gникогда не использовать в научной нотации;-).
вы могли бы использовать
%gдля достижения этого:'%g'%(3.140)или, для Python 2.6 или лучше:
'{0:g}'.format(3.140)С docs for
format:gпричин (среди прочего)незначительные конечные нули [быть] удалено из значащего, и десятичная точка также удаляется, если есть не останется ни одной цифры, следующие за ним.
после просмотра ответов на несколько подобных вопросов, это, кажется, лучшее решение для меня:
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(), но это имеет несколько проблем. Во-первых, это намного медленнее (~11x). Я также обнаружил, что, хотя он имеет довольно большую точность, он все еще страдает от потери точности при использованииnormalize().>>> Decimal('0.21000000000000000000000000006').normalize() Decimal('0.2100000000000000000000000001') >>> Decimal('0.21000000000000000000000000006') Decimal('0.21000000000000000000000000006')самое главное, я все равно буду конвертировать в
DecimalС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
Как насчет того, чтобы попробовать самый простой и, вероятно, самый эффективный подход? Метод нормализация() удаляет все правые нули.
from decimal import Decimal print (Decimal('0.001000').normalize()) # Result: 0.001работает в Python 2 и Python 3.
-- обновление --
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()
вы можете просто использовать формат () для достижения этой цели:
format(3.140, '.10g')где 10-это точность, которую вы хотите.
в то время как форматирование, вероятно, что наиболее Pythonic способ, Вот альтернативное решение с помощью
more_itertools.rstrip.import more_itertools as mit def fmt(num, pred=None): iterable = str(num) predicate = pred if pred is not None else lambda x: x in {".", "0"} return "".join(mit.rstrip(iterable, predicate)) assert fmt(3) == "3" assert fmt(3.) == "3" assert fmt(3.0) == "3" assert fmt(3.1) == "3.1" assert fmt(3.14) == "3.14" assert fmt(3.140) == "3.14" assert fmt(3.14000) == "3.14" assert fmt("3,0", pred=lambda x: x in set(",0")) == "3"число преобразуется в строку, которая лишается конечных символов, удовлетворяющих предикату. Определение функции
fmtне требуется, но он используется здесь для проверки утверждений, которые все проходят. Примечание: он работает на строковых входах и принимает необязательные предикаты.Смотрите также подробную информацию об этой сторонней библиотеке,
more_itertools.
Если вы можете жить с 3. и 3.0 появляется как "3.0", очень простой подход, который справа удаляет нули из представлений float:
print("%s"%3.140)(спасибо @ellimilial за указание исключений)
используйте %g с достаточно большой шириной, например'%.99g'. Он будет печатать в фиксированной точке для любого достаточно большого числа.
EDIT: это не работает
>>> '%.99g' % 0.0000001 '9.99999999999999954748111825886258685613938723690807819366455078125e-08'
OP хотел бы удалить суперфлуоус нули и сделать полученную строку как можно короче.
Я нахожу, что экспоненциальное форматирование %g сокращает полученную строку для очень больших и очень малых значений. Проблема возникает для значений, которые не нуждаются в экспоненциальной нотации, например 128.0, которая не является ни очень большой, ни очень маленькой.
вот один из способов форматирования чисел в виде коротких строк, который использует % G экспоненциальную нотацию только при десятичной.нормализация создает строки это слишком долго. Это может быть не самое быстрое решение (так как оно использует десятичное число.нормализовать)
def floatToString (inputValue, precision = 3): rc = str(Decimal(inputValue).normalize()) if 'E' in rc or len(rc) > 5: rc = '{0:.{1}g}'.format(inputValue, precision) return rc inputs = [128.0, 32768.0, 65536, 65536 * 2, 31.5, 1.000, 10.0] outputs = [floatToString(i) for i in inputs] print(outputs) # ['128', '32768', '65536', '1.31e+05', '31.5', '1', '10']