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

Python Decimal.quantize方法疑问:负数ROUND_UP舍入行为异常

问题:Decimal ROUND_UP 舍入异常分析

我用以下代码将浮点数截断到12位小数:

Decimal(val).quantize(Decimal(1).scaleb(-12), rounding=ROUND_UP)

测试时发现一个异常用例,除t4外其余输出均符合预期:

测试代码

from decimal import Decimal, ROUND_UP

t1 = Decimal(-0.04).quantize(Decimal(1).scaleb(-2), rounding=ROUND_UP)
print(f"t1: {t1}")
t2 = Decimal(-0.05).quantize(Decimal(1).scaleb(-2), rounding=ROUND_UP)
print(f"t2: {t2}")
t3 = Decimal(-0.22).quantize(Decimal(1).scaleb(-2), rounding=ROUND_UP)
print(f"t3: {t3}")

t4 = Decimal(-0.092314564913).quantize(Decimal(1).scaleb(-12), rounding=ROUND_UP)
print(f"t4: {t4}")
t5 = Decimal(-0.092314564914).quantize(Decimal(1).scaleb(-12), rounding=ROUND_UP)
print(f"t5: {t5}")
t6 = Decimal("-0.09231456491391342377614447500").quantize(Decimal(1).scaleb(-12), rounding=ROUND_UP)
print(f"t6: {t6}")

输出结果

t1: -0.05
t2: -0.06
t3: -0.23
t4: -0.092314564913
t5: -0.092314564915
t6: -0.092314564914

原因分析

核心问题在于二进制浮点数的精度限制:

  • 像-0.092314564913这类十进制小数无法用二进制浮点数精确存储,实际内存中的值会略大于字面量(更接近0),比如实际为-0.09231456491299999xxxx。
  • 当把这个浮点数转换为Decimal时,得到的数值小数点后12位恰好是-0.092314564913,没有超出12位的剩余部分,因此quantize配合ROUND_UP无需进行舍入,直接保留原12位小数。
  • t5中的-0.092314564914作为浮点数,实际存储值会略小于字面量(更负),转换为Decimal后小数点后12位之后还有超出部分,ROUND_UP会向远离0的方向舍入到-0.092314564915。
  • t6用字符串直接初始化Decimal,保证了数值的精确性,小数点后12位之后的913...触发ROUND_UP,最终舍入到-0.092314564914。

解决方案

如果需要精确处理十进制小数,建议使用字符串而非浮点数初始化Decimal,从根源避免二进制浮点数的精度误差影响结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 22:08:28