2010-07-16 2 views
12

У меня есть несколько списков и более сложные структуры, содержащие поплавки. При их печати я вижу поплавки с большим количеством десятичных цифр, но при печати мне не нужны все. Итак, я хотел бы определить пользовательский формат (например, 2 или 3 десятичных знака) при печати поплавков.Изменить формат печати поплавков

Мне нужно использовать поплавки, а не десятичные. Кроме того, мне не разрешено обрезать/круглые поплавки.

Есть ли способ изменить поведение по умолчанию?

ответ

7

Вам не разрешено для monkeypatch типов C, как сказал Игнасио.

Однако, если вы ужасно нажали на это, и вы знаете некоторые C, вы можете сами изменить исходный код интерпретатора Python, а затем перекомпилировать его в настраиваемое решение. Как только я изменил одно из стандартных режимов для списков, и это была только умеренная боль.

Я предлагаю вам найти лучшее решение, например, просто печатая поплавки с "%0.2f" PRINTF нотации:

for item in mylist: 
    print '%0.2f' % item, 

или

print " ".join('%0.2f' % item for item in mylist) 
+0

Проблема в том, что я плаваю внутри списков, и когда я печатаю (список), я не контролирую это. (Это относится и к другим объектам, кстати). Изменение исходного кода возможно, так как я знаю C, но не совсем то, о чем я думал. Благодарю. – AkiRoss

+0

@AkiRoss: Итак, то, что вы хотите исправить, это список, а не поплавки ... –

+0

@AkiRoss, если вы хотите большего контроля, просто распечатайте элементы отдельно. –

3

Нет, поскольку это потребует модификации float.__str__(), но вам не разрешено использовать типы monkeypatch C. Вместо этого используйте строчную интерполяцию или форматирование.

+0

На самом деле это потребует модификации 'float .__ repr__'.'str' использует только 12 значащих цифр. – dan04

1
>>> a = 0.1 
>>> a 
0.10000000000000001 
>>> print a 
0.1 
>>> print "%0.3f" % a 
0.100 
>>> 

С Python docs, repr(a) даст 17 цифр (как видно, просто набрав a в интерактивном режиме, но str(a) (выполняется автоматически при печати) округляется до 12.

Edit: Most основное решение хак ... Вы должны использовать свой собственный класс, хотя, так что ... да.

>>> class myfloat(float): 
...  def __str__(self): 
...    return "%0.3f" % self.real 
>>> b = myfloat(0.1) 
>>> print repr(b) 
0.10000000000000001 
>>> print b 
0.100 
>>> 
0

Обновление до 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 
+0

Уже использовал его. Это не главное, но спасибо за подсказку. – AkiRoss

-1

Если вы используете язык C, вы можете использовать либо #define или "%*.*f", чтобы сделать это, например,

printf("%*.*f",4,2,variable); 
+1

Он явно использует теги python, поэтому он не использует C – Bruce

2

Сегодня я столкнулся с этим вопросом, и я придумал другое решение. Если вы беспокоитесь о том, как это выглядит при печати, вы можете заменить стандартный файл stdout на пользовательский, который при вызове write() ищет любые вещи, которые выглядят как float, и заменяет их собственным форматом для их.

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, я понятия не имею, будет ли это работать.

Смежные вопросы