【问题标题】:Why Django DecimalField let me store Float or string?为什么 Django DecimalField 让我存储浮点数或字符串?
【发布时间】:2018-01-28 10:17:43
【问题描述】:

我不明白Django DecimalField 的行为。

定义为:

一个固定精度的十进制数,在 Python 中由一个 Decimal 实例表示。

但是,使用以下模型:

class Article(models.Model)
    unit_price = DecimalField(max_digits=9, decimal_places=2)

我可以通过至少 3 种方式创建文章:

article = Article.objects.create(unit_price="2.3")
type(article.unit_price)
>>> str

article = Article.objects.create(unit_price=2.3)
type(article.unit_price)
>>> float

article = Article.objects.create(unit_price=Decimal('2.3'))
type(article.unit_price)
>>> decimal.Decimal

为什么 Django DecimalField 能够返回 Decimal 类型以外的东西?

确保我的应用永远不会处理浮动价格的最佳方法是什么?

谢谢。

【问题讨论】:

    标签: python django floating-point decimal


    【解决方案1】:

    为什么 Django DecimalField 能够返回 Decimal 以外的东西 输入?

    这是因为 Django 在模型创建期间是允许的,并且允许您在这些字段中输入任何类型而不会出错,如果您输入的内容可以强制转换为指定的类型。

    将它插入数据库后,它会得到正确的类型。您可以使用refresh_from_db() 验证这一点:

    article = Article.objects.create(unit_price="2.3")
    type(article.unit_price)
    >>> str
    article.refresh_from_db()
    type(article.unit_price)
    >>> decimal.Decimal
    

    确保我的应用永远不会处理浮点数的最佳方法是什么 价格?

    确保这一点的唯一方法是在您知道价格金额后立即强制将任何价格输入到decimal.Decimal

    【讨论】:

      【解决方案2】:

      嗯,decimal.Decimal 子类型本身就是 float,这就是为什么它在您的模型中被接受。 decimal.Decimal 类型为浮点类型提供了进一步的算术精度。

      如十进制类型docs中解释,操作:

      0.1 + 0.1 + 0.1 - 0.3
      

      使用decimal.Decimal 精确地给出0,因为在float 类型中给出一个接近于零的数字:

      5.5511151231257827e-017
      

      最后,decimal.Decimal 数字可以准确表示。

      十进制数是不可变的。它有符号、系数数字和 一个指数。为了保持显着性,系数数字不 截断尾随零。小数还包括特殊值,例如 无穷大、-无穷大和 NaN。该标准还将 -0 与 +0。

      为了在您的应用程序中使用显式小数,您还必须显式并注意小数转换、每个 db 输入/输出或使用强制转换为 decimal.Decimal 的序列化操作。

      要进一步了解浮点运算在后台的故事,您可以访问Decimal Arithmetic Specification

      【讨论】:

      • 我认为“decimal.Decimal 子类型本身就是一个浮点数”的说法具有误导性。 Decimal 更类似于 int 而不是浮点数。它是一个定点整数,基本上是一个具有定义的固定小数点的整数。浮点数由尾数和指数组成。整数和小数没有指数的概念。这就是为什么它们对于相同的位数更准确。虽然它们的动态范围当然更低。
      猜你喜欢
      • 2023-03-18
      • 1970-01-01
      • 2015-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多