我的DecimalField上不一致出现尾随零

1 投票
1 回答
710 浏览
提问于 2025-04-18 05:10

我想用一个DecimalField来处理小数,要求有6位小数,现在我在一个独立的模型里测试这个功能:

class MyItem(models.Model):
    myval = models.DecimalField(max_digits=18, decimal_places=6)
    def __str__(self):
        return str(self.myval)

目前我在使用内置的管理界面,观察到以下情况:

  • 输入最多4位小数的值(比如0.0001)是正常的
  • 输入大于1的值也没问题

但是,像0.000010.000001这样的值会显示成带有尾随零的形式,也就是0.000010

虽然从数学上讲这是正确的(数字是一样的),而且我可以通过一些小操作去掉这个零,但我觉得有点困扰,因为有时候这个零会出现,有时候又不会。我也没有测试过很多不同的数字,所以不确定所有数字的正确值是否真的会被保存。

根据我的理解,DecimalField应该是保持精确的。我在创建模型时是不是漏掉了什么基本的东西?这是怎么回事呢?

我使用的版本是Python 3.3和Django 1.6

1 个回答

1

这里有一个对DecimalField模型的重写,应该能解决这个问题,具体内容可以在这里找到:

class NonscientificDecimalField(DecimalField):
    """ Prevents values from being displayed with E notation, with trailing 0's
        after the decimal place  truncated. (This causes precision to be lost in
        many cases, but is more user friendly and consistent for non-scientist
        users)
    """
    def value_from_object(self, obj):
        def remove_exponent(val):
            """Remove exponent and trailing zeros.
               >>> remove_exponent(Decimal('5E+3'))
               Decimal('5000')
            """
            context = decimal.Context(prec=self.max_digits)
            return val.quantize(decimal.Decimal(1), context=context) if val == val.to_integral() else val.normalize(context)

        val = super(NonscientificDecimalField, self).value_from_object(obj)
        if isinstance(val, decimal.Decimal):
            return remove_exponent(val)

撰写回答