Изменить формат печати по умолчанию
У меня есть несколько списков и более сложные структуры, содержащие поплавки. При их печати я вижу числа с большим количеством десятичных цифр, но при печати они мне не нужны. Поэтому я хотел бы определить пользовательский формат (например, 2 или 3 десятичных знака) при печати с плавающей точкой.
Мне нужно использовать поплавки, а не десятичные. Кроме того, мне не разрешено усекать / округлять поплавки.
Есть ли способ изменить поведение по умолчанию?
9 ответов
Как сказал Игнасио, вам не разрешено монтировать патчи C-типов.
Однако, если вы ужасно переживаете это и знаете какой-то C, вы можете сами изменить исходный код интерпретатора Python, а затем скомпилировать его в собственное решение. Однажды я изменил одно из стандартных поведений для списков, и это была только умеренная боль.
Я предлагаю вам найти лучшее решение, например, просто распечатать поплавки с "%0.2f"
нотация printf:
for item in mylist:
print '%0.2f' % item,
или же
print " ".join('%0.2f' % item for item in mylist)
Это не отвечает на более общий вопрос о числах с плавающей запятой, вложенных в другие структуры, но если вам просто нужно напечатать числа с плавающей запятой в списках или даже в виде вложенных списков в виде массива, рассмотрите возможность использования numpy
.
например,
import numpy as np
np.set_printoptions(precision=3, suppress=False)
list_ = [[1.5398, 2.456, 3.0],
[-8.397, 2.69, -2.0]]
print(np.array(list_))
дает
[[ 1.54 2.456 3. ]
[-8.397 2.69 -2. ]]
>>> a = 0.1
>>> a
0.10000000000000001
>>> print a
0.1
>>> print "%0.3f" % a
0.100
>>>
Из документов Python, repr(a)
даст 17 цифр (как видно, просто набрав a
в интерактивном режиме, но str(a)
(выполняется автоматически при печати) округляет до 12.
Изменить: Основное решение взломать... Вы должны использовать свой собственный класс, хотя, так что... да.
>>> class myfloat(float):
... def __str__(self):
... return "%0.3f" % self.real
>>> b = myfloat(0.1)
>>> print repr(b)
0.10000000000000001
>>> print b
0.100
>>>
Нет, потому что это потребует изменения float.__str__()
, но вам не разрешено монкипечать C-типы. Вместо этого используйте строковую интерполяцию или форматирование.
Я столкнулся с этой проблемой сегодня, и я нашел другое решение. Если вы беспокоитесь о том, как это выглядит при печати, вы можете заменить объект файла stdout на пользовательский, который при вызове write() выполняет поиск любых объектов, которые выглядят как плавающие, и заменяет их собственным форматом для их.
class ProcessedFile(object):
def __init__(self, parent, func):
"""Wraps 'parent', which should be a file-like object,
so that calls to our write transforms the passed-in
string with func, and then writes it with the parent."""
self.parent = parent
self.func = func
def write(self, str):
"""Applies self.func to the passed in string and calls
the parent to write the result."""
return self.parent.write(self.func(str))
def writelines(self, text):
"""Just calls the write() method multiple times."""
for s in sequence_of_strings:
self.write(s)
def __getattr__(self, key):
"""Default to the parent for any other methods."""
return getattr(self.parent, key)
if __name__ == "__main__":
import re
import sys
#Define a function that recognises float-like strings, converts them
#to floats, and then replaces them with 1.2e formatted strings.
pattern = re.compile(r"\b\d+\.\d*\b")
def reformat_float(input):
return re.subn(pattern, lambda match: ("{:1.2e}".format(float(match.group()))), input)[0]
#Use this function with the above class to transform sys.stdout.
#You could write a context manager for this.
sys.stdout = ProcessedFile(sys.stdout, reformat_float)
print -1.23456
# -1.23e+00
print [1.23456] * 6
# [1.23e+00, 1.23e+00, 1.23e+00, 1.23e+00, 1.23e+00, 1.23e+00]
print "The speed of light is 299792458.0 m/s."
# The speed of light is 3.00e+08 m/s.
sys.stdout = sys.stdout.parent
print "Back to our normal formatting: 1.23456"
# Back to our normal formatting: 1.23456
Бесполезно, если вы просто помещаете числа в строку, но в итоге вам, вероятно, захочется записать эту строку в какой-нибудь файл, и вы сможете обернуть этот файл указанным выше объектом. Очевидно, что это немного снижает производительность.
Справедливое предупреждение: я не проверял это в Python 3, я понятия не имею, будет ли это работать.
Для тех, кто работает в пандах:
pd.options.display.float_format = "{:,.0f}".format
Я знаю, что это «старый» пост, но когда я быстро ищу в Интернете это решение, я часто нахожу старые «обходные пути». Заранее извиняюсь, если что-то совсем упустил.
Приведенный выше код форматирует все числа с плавающей запятой как целые числа с разделителем тысяч. Другие десятичные знаки можно получить, изменив строку спецификации формата.
Предупреждение о работоспособности — это может усложнить отладку, поскольку все выходные данные (например, «печать», «отображение» и «описание») также будут выводить должным образом округленные цифры. Это может быть проблематично, если некоторые числа с плавающей запятой будут отображаться по-другому (т. е. округляться), хотя на самом деле они имеют другое значение.
Я только что придумал способ добиться этого, по крайней мере, для симпатичных выражений, см. this . С двумя приведенными ниже функциями замените каждыйprint(...
сprint_my(...
. Это кажется мне чрезвычайно менее надуманным, простым в использовании и универсальным, чем большинство других опубликованных решений.
я подозреваю, что мойround_expr
можно легко адаптировать для несимптомных выражений, что является недостающим звеном для полного ответа.
def round_expr(expr, num_digits):
"""Round all sp.Float numerical values in an expression to 3 decimal digits"""
return expr.xreplace({n.evalf() : n if isinstance(n, int) else sp.Float(n, num_digits) for n in expr.atoms(sp.Number)})
def print_my(*args, **kwargs):
end_my = kwargs['end'] if 'end' in kwargs else '\n'
sep_my = kwargs['sep'] if 'sep' in kwargs else ' '
for arg in args:
if (isinstance(arg, str)):
print(arg, end=sep_my)
else:
print(round_expr(arg, 3), end=sep_my)
print(end=end_my)
return
Если вы используете язык C, вы можете использовать #define
или же "%*.*f"
сделать это, например,
printf("%*.*f",4,2,variable);
Обновление до Python 3.1. Он не использует больше цифр, чем необходимо.
Python 3.1.2 (r312:79147, Apr 15 2010, 15:35:48)
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 0.1
0.1