You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django中小数四舍五入不符合预期,如何实现指定结果?

Django 3.2.16 实现传统四舍五入的解决方案

问题原因

Django 3.2的Round函数默认采用银行家舍入法(四舍六入五成双),即当舍去位为5且后续无有效数字时,会将前一位调整为偶数。这与你需要的「逢5进1」传统四舍五入逻辑不一致,导致结果不符合预期。

解决方案

由于Django 3.2未提供修改舍入模式的参数,我们可以通过数学运算手动模拟传统四舍五入逻辑:

跨数据库通用方案

from django.db.models import ExpressionWrapper, F, Cast, Floor
from django.db.models.fields import FloatField, IntegerField

amount_annotation = ExpressionWrapper(
    # 逻辑:原始值*100 +0.5 后取整,直接得到目标整数结果
    Floor(
        (F(amount_field) * (Cast(F('income__ownership'), FloatField()) / 10000)) * 100 + 0.5
    ),
    output_field=IntegerField()
)

逻辑说明

  1. 先计算原始乘积:F(amount_field) * (Cast(F('income__ownership'), FloatField()) / 10000)
  2. 乘以100将两位小数位转至整数部分:比如37.715 * 100 = 3771.5
  3. 加0.5实现逢5进1:3771.5 + 0.5 = 3772.0
  4. 用Floor取整得到最终整数结果:3772

数据库特定方案(以PostgreSQL为例)

如果你的项目基于PostgreSQL,可以直接调用数据库原生ROUND函数并指定舍入模式:

from django.db.models import Func, ExpressionWrapper, F, Cast
from django.db.models.fields import FloatField, IntegerField

class TraditionalRound(Func):
    function = 'ROUND'
    template = "%(function)s(%(expressions)s, 2, 'plain')"

amount_annotation = ExpressionWrapper(
    TraditionalRound(
        F(amount_field) * (Cast(F('income__ownership'), FloatField()) / 10000)
    ) * 100,
    output_field=IntegerField()
)

内容的提问来源于stack exchange,提问作者user369287

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 02:56:33