jacktengg commented on code in PR #67850:
URL: https://github.com/apache/doris/pull/67850#discussion_r3999955584
##########
be/src/exprs/function/cast/cast_to_decimal.h:
##########
Review Comment:
这里有一个从很老版本带下来的bug:
AI review comments:
• 逻辑不完全正确,存在三个可复现的问题。 我用独立 C++ 程序复现了相关算术表达式;没有修改源码,也没有运行 Doris 集成测
试。
这个函数的意图是:排除 NaN/Inf → 乘以 10^scale → 检查范围 → 四舍五入得到 Decimal
的底层整数。问题出在范围检查和舍入实
现。
1. 范围检查误拒绝合法值
第 251 行 (be/src/exprs/function/cast/cast_to_decimal.h:251):
if (tmp <= DoubleType(min_result) || tmp >= DoubleType(max_result))
这里 max_result = 10^precision - 1,是允许取到的最大底层整数,不是排他的上界。
以 DECIMAL(1,0) 为例:
DOUBLE 输入 正确结果 当前行为
━━━━━━━━━━━━━ ━━━━━━━━━━ ━━━━━━━━━━
9.0 9 判溢出
───────────── ────────── ──────────
-9.0 -9 判溢出
───────────── ────────── ──────────
9.25 9 判溢出
───────────── ────────── ──────────
-9.25 -9 判溢出
因此,仅把 <= / >= 改成 < / > 仍不够:9.25 虽然舍入前超过 9,舍入后仍合法。范围判断必须考虑最终舍入结果。
调用方会把这些误判变成严格模式报错、非严格模式返回 NULL。
2. “加减 0.5 再截断”不等价于正确的四舍五入
第 258 行 (be/src/exprs/function/cast/cast_to_decimal.h:258):
static_cast<NativeType>(static_cast<double>(
from * static_cast<DoubleType>(scale_multiplier)
+ ((from >= 0) ? 0.5 : -0.5)))
明确反例:
输入 DOUBLE:4503599627370497,即 2^52 + 1
目标类型: DECIMAL(16,0)
正确结果: 4503599627370497
当前结果: 4503599627370498
输入本身能被 double 精确表示。但此处相邻 double 的间距为 1,加 0.5 后按默认浮点舍入规则变成相邻偶数,随后转整数已无法
恢复。
小数也有反例:
输入:nextafter(0.5, 0.0) = 0.49999999999999994
正确舍入:0
当前结果:1
应使用 std::round 等明确实现所需舍入规则的操作;这只能解决舍入步骤,缩放精度和范围仍需单独处理。
3. Decimal256 路径又转回 double,损失中间精度
第 249 行为 Decimal256 选择 long double,但第 258 行强制缩窄成 double。
本机 long double 有 64 位有效二进制精度,复现结果:
输入 DOUBLE:9007199254740991(可精确表示)
目标类型: DECIMAL(39,1)
long double 缩放结果:90071992547409910(精确)
转回 double 后: 90071992547409904
正确 Decimal:9007199254740991.0
当前 Decimal:9007199254740990.4
这是转换过程中新增的误差,且函数返回成功。修复需要提供保留中间精度的整数转换路径;不能只删除 static_cast<double>,还
需核对 Int256 对 long double 的构造支持。
现有测试不能有效证明这些逻辑正确。
测试辅助函数第 1450 行起
(be/test/exprs/function/cast/cast_to_decimal_test.h:1450)复制了相同的范围判断,跳过这些边界输入,并用相同的“加减
0.5、转 double”公式生成期望值,因此会掩盖上述错误。应补充独立确定期望值的正负端点、舍入边界、大整数及 Decimal256 用例。
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]