在Python中子类化float以强制固定小数点打印精度

2 投票
3 回答
1730 浏览
提问于 2025-04-16 06:31

[Python 3.1]

我在跟进这个回答

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

我知道我需要注意我的浮点数(也就是把 3.0 替换成 prettyfloat(3.0) 等等),这没问题。

但是每当我进行计算时,prettyfloat 对象就会变成 float

有什么简单的方法可以解决这个问题吗?

编辑:

我需要保留两位小数;而且我希望在整个代码中都能这样,包括打印一个包含 float 值的字典。这让任何格式化函数都很难使用。

我不能使用 Decimal 的全局设置,因为我希望计算保持高精度(只是打印时保留两位小数)。

@Glenn Maynard:我同意我不应该重写 __repr__;如果要重写的话,应该是 __str__。不过这并不重要,因为有以下的原因。

@Glenn Maynard 和 @singularity:我不会去继承 float,因为我同意这样最终看起来会很糟糕。

我决定不再尝试聪明的做法,而是在每次打印 float 的地方都调用一个函数。虽然我真的很遗憾不能在内置的 float 类中重写 __str__

谢谢大家!

3 个回答

1

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

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

...除非你真的想在代码中到处使用高精度的浮点数,但在打印的时候只显示到小数点后两位。那样的话,你就需要重新调整你的打印逻辑。

3

这是因为 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 :) 希望这能帮到你。

5

我看了你提到的那个回答,觉得你可能搞混了数据和它的表现形式

@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.

现在,如果这根本不是关于表现形式的问题,而是你想在代码中实现固定小数点的计算,并且限制在两位小数,那就完全是另一回事了。

撰写回答