python 更改默认浮动打印格式

4dbbbstv  于 2023-01-08  发布在  Python
关注(0)|答案(8)|浏览(129)

我有一些包含浮点数的列表和更复杂的结构。当打印它们时,我看到浮点数有很多小数位,但当打印时,我不需要所有的小数位。所以我想定义一个自定义格式(例如2或3位小数)来打印浮点数。
我需要使用浮点数,而不是十进制数。而且,我不允许截断/舍入浮点数。
是否有办法更改默认行为?

nfeuvbwi

nfeuvbwi1#

就像伊格纳西奥说的,你不允许monkeypatch C类型。
然而,如果你非常迫切地要这么做,并且你懂一些C语言,你可以自己去修改Python解释器源代码,然后重新编译成一个定制的解决方案。有一次我修改了列表的一个标准行为,这只是一个中等程度的痛苦。
我建议您找到一个更好的解决方案,比如只使用"%0.2f" printf符号打印浮点数:

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

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

cig3rfwq2#

>>> 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位。

**编辑:最基本的黑客解决方案...**你必须使用自己的类,所以...是的。

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

os8fio9y3#

这并没有回答嵌套在其他结构中的浮点数这个更一般的问题,但是如果只需要打印列表中的浮点数,甚至是类似数组的嵌套列表,可以考虑使用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.   ]]
mwngjboj

mwngjboj4#

不可以,因为这需要修改float.__str__(),但是不允许monkeypatch C类型。请使用字符串插值或格式化。

uqzxnwby

uqzxnwby5#

我今天遇到了这个问题,我想出了一个不同的解决方案。如果你担心打印出来的效果,你可以用一个自定义对象替换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

如果你只是把数字写进一个字符串,这是不好的,但最终你可能会想把这个字符串写进某个文件中,你也许可以用上面的对象 Package 这个文件,显然这会有一点性能开销。
善意警告:我还没有在Python 3中测试过,我不知道它是否能工作。

rur96b6h

rur96b6h6#

我刚刚整理了一个实现这个的方法,至少对于symy表达式,请参见this。使用下面的两个函数,用print_my(...替换每个print(...。在我看来,这比大多数其他发布的解决方案更不做作,更容易使用,而且功能更广泛。
我怀疑我的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
fhity93d

fhity93d7#

升级到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
kqqjbcuj

kqqjbcuj8#

如果您使用的是C语言,则可以使用#define"%*.*f"来执行此操作,例如:

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

相关问题