python 3.7 和 Django 中金额的前 2 位小数舍入错误
Wrong decimal round to first 2 digits of amounts in python 3.7 and Django
假设有 3 个 Django 字段:
INPUT = models.DecimalField(max_digits=20, decimal_places=3, default=0)
RESULT = models.DecimalField(max_digits=20, decimal_places=3, default=0)
RATE = models.DecimalField(max_digits=12, decimal_places=5, default=1)
RATE
总是 Decimal('1.00000')
.
我想要 RESULT = INPUT * RATE
并且由于来源要么来自数据库,要么来自 API,我使用:
RESULT = Decimal(INPUT) * Decimal(RATE)
我不知道为什么,但在某些情况下 (≈ 2%) 我以您在下面看到的数字结尾 table。前2位有舍入。
你知道是什么原因造成的吗?我在代码中看不到任何可以做到这一点的东西,而且我一无所知。 两列应该相等。
RESULT INPUT
610.000 609.000
3700.000 3743.520
1200.000 1159.000
570.000 573.300
61.000 61.470
1300.000 1321.550
44.000 43.730
130.000 125.770
18.000 18.500
100.000 99.590
41.000 40.650
95.000 94.880
19.000 18.710
36.000 35.640
120.000 118.800
12.000 12.290
11.000 11.260
1.000 1.030
160.000 155.970
190.000 186.850
51.000 50.770
130.000 128.150
12.000 12.290
11.000 11.260
25.000 24.940
24.000 23.640
看来是小数上下文精度的原因:
getcontext().prec = 2
在代码的某处,它已被设置,并且永远不会重置。这是精度为 2 时发生的情况:
>>> import decimal
>>> decimal.getcontext()
Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[InvalidOperation, Inexact, FloatOperation, Rounded], traps=[InvalidOperation, DivisionByZero, Overflow])
>>> decimal.getcontext().prec = 2
>>> decimal.getcontext()
Context(prec=2, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[InvalidOperation, Inexact, FloatOperation, Rounded], traps=[InvalidOperation, DivisionByZero, Overflow])
>>> Decimal(3.21)
Decimal('3.20999999999999996447286321199499070644378662109375')
>>> Decimal(3.21) * Decimal(1)
Decimal('3.2')
>>> Decimal(58341)
Decimal('58341')
>>> Decimal(58341) * Decimal(1)
Decimal('5.8E+4')
假设有 3 个 Django 字段:
INPUT = models.DecimalField(max_digits=20, decimal_places=3, default=0)
RESULT = models.DecimalField(max_digits=20, decimal_places=3, default=0)
RATE = models.DecimalField(max_digits=12, decimal_places=5, default=1)
RATE
总是 Decimal('1.00000')
.
我想要 RESULT = INPUT * RATE
并且由于来源要么来自数据库,要么来自 API,我使用:
RESULT = Decimal(INPUT) * Decimal(RATE)
我不知道为什么,但在某些情况下 (≈ 2%) 我以您在下面看到的数字结尾 table。前2位有舍入。
你知道是什么原因造成的吗?我在代码中看不到任何可以做到这一点的东西,而且我一无所知。 两列应该相等。
RESULT INPUT
610.000 609.000
3700.000 3743.520
1200.000 1159.000
570.000 573.300
61.000 61.470
1300.000 1321.550
44.000 43.730
130.000 125.770
18.000 18.500
100.000 99.590
41.000 40.650
95.000 94.880
19.000 18.710
36.000 35.640
120.000 118.800
12.000 12.290
11.000 11.260
1.000 1.030
160.000 155.970
190.000 186.850
51.000 50.770
130.000 128.150
12.000 12.290
11.000 11.260
25.000 24.940
24.000 23.640
看来是小数上下文精度的原因:
getcontext().prec = 2
在代码的某处,它已被设置,并且永远不会重置。这是精度为 2 时发生的情况:
>>> import decimal
>>> decimal.getcontext()
Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[InvalidOperation, Inexact, FloatOperation, Rounded], traps=[InvalidOperation, DivisionByZero, Overflow])
>>> decimal.getcontext().prec = 2
>>> decimal.getcontext()
Context(prec=2, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[InvalidOperation, Inexact, FloatOperation, Rounded], traps=[InvalidOperation, DivisionByZero, Overflow])
>>> Decimal(3.21)
Decimal('3.20999999999999996447286321199499070644378662109375')
>>> Decimal(3.21) * Decimal(1)
Decimal('3.2')
>>> Decimal(58341)
Decimal('58341')
>>> Decimal(58341) * Decimal(1)
Decimal('5.8E+4')