【问题标题】:subclassing float to force fixed point printing precision in python子类化浮点数以强制python中的定点打印精度
【发布时间】:2010-11-03 23:43:10
【问题描述】:

[Python 3.1]

我正在跟进this answer

class prettyfloat(float):
  def __repr__(self):
    return "%0.2f" % self

我知道我需要跟踪我的浮点字面量(即将3.0 替换为prettyfloat(3.0) 等),这很好。

但每当我进行任何计算时,prettyfloat 对象都会转换为 float

最简单的修复方法是什么?

编辑:

我需要两个十进制数字;我在整个代码中都需要它,包括在其中打印带有float 值的字典。这使得任何格式化函数都难以使用。

我不能使用 Decimal 全局设置,因为我希望计算是完全精确的(只打印 2 个小数点)。

@Glenn Maynard:我同意我不应该覆盖__repr__;如果有的话,那就是__str__。但由于以下几点,这是一个没有实际意义的问题。

@Glenn Maynard 和@singularity:我不会继承float,因为我同意它最终会看起来很丑。

我将不再试图变得聪明,而是在打印float 的任何地方调用一个函数。虽然我真的很难过我不能在内置类float 中覆盖__str__

谢谢!

【问题讨论】:

  • 最简单的格式化格式可能是使用decimal.Decimal。这有什么问题?
  • 我还没有看到这样的案例,其中子类化像 float 这样的核心类型是正确的做法。
  • @S.Lott 我需要两个十进制数字;我在整个代码中都需要它,包括在其中打印带有浮点值的字典的位置。 @Glenn Maynard 我也不抱太大希望:(只是想也许有一种干净的方法可以让它发挥作用。
  • 让一个类的repr 循环值是错误的行为,并且可能会以奇怪和微妙的方式破坏事情,因为 Python 代码应该能够依赖于 eval(repr(1.12345)) 是一个循环-行程操作。 repr 是处理格式的错误位置。
  • 更新您的问题以包含所有事实。请不要将 cmets 添加到您拥有的问题中。请更新问题。

标签: python floating-point python-3.x subclass built-in-types


【解决方案1】:

我查看了您跟进的答案,我认为您混淆了数据及其表示

@Robert Rossney 建议将float 子类化,这样您就可以将map() 一个可迭代的标准、非掺假floats 转换为prettyfloats 用于显示目的

# Perform all our computations using standard floats.
results = compute_huge_numbers(42)
# Switch to prettyfloats for printing.
print(map(prettyfloat, results))

换句话说,您不应该(也不应该)在代码中的任何位置使用prettyfloat 来替代float

当然,从float 继承来解决这个问题是多余的,因为这是一个表示问题而不是数据问题。一个简单的函数就足够了:

def prettyfloat(number):
    return "%0.2f" % number  # Works the same.

现在,如果它毕竟不是关于表示的,而您真正想要实现的是定点计算,在您的代码中任何地方都限制为两位小数,那完全是another story

【讨论】:

    【解决方案2】:

    因为prettyfloat (op) prettyfloat 不返回prettyfloat

    示例:

    >>> prettyfloat(0.6)
    0.60  # type prettyfloat
    >>> prettyfloat(0.6) + prettyfloat(4.4)
    5.0  # type float
    

    如果您不想手动将每个操作结果强制转换为prettyfloat 并且如果您仍想使用prettyfloat,解决方案是覆盖所有运算符。

    运算符__add__ 的示例(丑陋)

    class prettyfloat(float):
      def __repr__(self):
          return "%0.2f" % self
      def __add__(self, other):
          return prettyfloat(float(self) + other)
    
    >>> prettyfloat(0.6) + prettyfloat(4.4)
    5.00
    

    通过这样做,我认为您还必须将名称从 prettyfloat 更改为 uglyfloat :),希望这会有所帮助

    【讨论】:

    • 作为一个例子,你会遇到这种问题,prettyfloat(1.12345) + 1.123451.12345 + prettyfloat(1.12345) 的结果非常不同。
    • 是的,为什么他不应该这样做,他可以通过每次进行一些类型检查来解决这个问题,让它变得更丑:)
    【解决方案3】:

    使用decimal。这就是它的用途。

    >>> import decimal
    >>> decimal.getcontext().prec = 2
    >>> one = decimal.Decimal("1.0")
    >>> three = decimal.Decimal("3.0")
    >>> one / three
    Decimal('0.33')
    

    ...除非您真的想在代码中的任何地方使用全精度浮点数,但将它们四舍五入到小数点后两位。在这种情况下,你需要重写你的打印逻辑。

    【讨论】:

    • 这改变了值的精度,而不仅仅是它的显示方式,这是非常不同的。我还必须认真质疑具有全局配置的模块的设计能力。如果您使用一个(或多个)在幕后使用此模块的库,那么很难想象有多少晦涩难懂且难以修复的方式会被上下文配置更改所困扰。
    • (我希望他们能修复网站错误,让人们编辑答案而不显示为已编辑。)
    • @Glenn:我相信发帖后会有一个短暂的窗口,您可以在其中进行编辑,而无需将您的帖子标记为已编辑。你确实是对的,当然 =)。
    猜你喜欢
    • 1970-01-01
    • 2021-07-25
    • 1970-01-01
    • 2020-08-04
    • 2012-06-09
    • 2015-02-02
    • 1970-01-01
    • 2019-09-15
    • 1970-01-01
    相关资源
    最近更新 更多