这可能与Polars DataFrame - Decimal Precision 在 Integer 乘法上加倍有关。
我在极坐标 (v1.6.0) 乘法的各个阶段遇到了舍入问题。以下是示例:
from decimal import Decimal
import polars as pl
df = pl.DataFrame({
"a": [2, 5],
"b": [Decimal('2.0'), Decimal('5.0')],
"c": [Decimal('2.00'), Decimal('5.00')],
"d": [Decimal('2.000'), Decimal('5.000')],
"e": [Decimal('2.0000'), Decimal('5.0000')]
})
shape: (2, 5)
┌─────┬──────────────┬──────────────┬──────────────┬──────────────┐
│ a ┆ b ┆ c ┆ d ┆ e │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ i64 ┆ decimal[*,1] ┆ decimal[*,2] ┆ decimal[*,3] ┆ decimal[*,4] │
╞═════╪══════════════╪══════════════╪══════════════╪══════════════╡
│ 2 ┆ 2.0 ┆ 2.00 ┆ 2.000 ┆ 2.0000 │
│ 5 ┆ 5.0 ┆ 5.00 ┆ 5.000 ┆ 5.0000 │
└─────┴──────────────┴──────────────┴──────────────┴──────────────┘
# Demo 1
# 10/71 = 0.14084507042253522
dfn = df.with_columns(
pl.col(col).mul(10/71)
for col in df.columns
)
shape: (2, 5)
┌──────────┬──────────────┬──────────────┬──────────────┬──────────────┐
│ a ┆ b ┆ c ┆ d ┆ e │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ f64 ┆ decimal[*,2] ┆ decimal[*,4] ┆ decimal[*,6] ┆ decimal[*,8] │
╞══════════╪══════════════╪══════════════╪══════════════╪══════════════╡
│ 0.28169 ┆ 0.20 ┆ 0.2800 ┆ 0.280000 ┆ 0.28160000 │
│ 0.704225 ┆ 0.50 ┆ 0.7000 ┆ 0.700000 ┆ 0.70400000 │
└──────────┴──────────────┴──────────────┴──────────────┴──────────────┘
# Demo 2
dfn = df.with_columns(
pl.col(col).mul(Decimal(10/71).quantize((Decimal('1.0000'))))
for col in df.columns
)
shape: (2, 5)
┌──────────────┬──────────────┬──────────────┬──────────────┬──────────────┐
│ a ┆ b ┆ c ┆ d ┆ e │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ decimal[*,8] ┆ decimal[*,5] ┆ decimal[*,6] ┆ decimal[*,7] ┆ decimal[*,8] │
╞══════════════╪══════════════╪══════════════╪══════════════╪══════════════╡
│ 0.28160000 ┆ 0.28160 ┆ 0.281600 ┆ 0.2816000 ┆ 0.28160000 │
│ 0.70400000 ┆ 0.70400 ┆ 0.704000 ┆ 0.7040000 ┆ 0.70400000 │
└──────────────┴──────────────┴──────────────┴──────────────┴──────────────┘
在Demo 1
上面,当我仅乘以 10/71 时,列b [decimal[*,1]
似乎乘以0.1
而不是0.140845...
,c decimal[*,2]
似乎乘以0.14
,d decimal[*,3]
乘以0.140
和。简而言之,无论乘以 10/71 的列的原始十进制比例是多少,似乎都使用相同的 10/71 比例e decimal[*,4]
。0.1408
如 所示Demo 2
,我必须先量化比例,然后才能将其用于乘法。请注意,我不能只使用.mul(Decimal(10/71))
而不量化,因为这样做会导致错误BindingsError: "Decimal is too large to fit in Decimal128"
。
有没有比强制缩放乘数更好的方法?
在我看来它正在做正确的事情,所以不清楚你想要什么更好的结果。
(尽管(在我看来)存在一个错误,但它的规模却加倍了)
另一个演示
因此 python Decimal 包甚至不会尝试执行 Decimal * float,所以很难说什么是“更好”。
正如您所注意到的,polars 似乎正在将浮点数转换为与左侧十进制相同的标度。我想不出比这更好的默认值了。
第一种选择
让极坐标执行两个整数运算,而不是让 Python 创建浮点数
在这种情况下,mul 会使比例加倍(我认为这是一个错误),然后除法似乎会将比例加 4,这是我无法弄清楚的(也许这也是一个错误或只是一个故意的硬编码默认值)。
第二种选择
使用 10/71 的十进制形式指定您想要的比例,例如
在这种情况下(忽略 a 列),它看起来像是在添加刻度。这与 的行为相同,所以
Decimal("2.00")*Decimal("0.1408")
我认为这是对的。