Skip to content

fix: preserve canonical floating-point BigDecimal conversion - #7819

Open
DarrenChangJR wants to merge 1 commit into
alibaba:mainfrom
DarrenChangJR:fix/big-decimal-double-conversion
Open

fix: preserve canonical floating-point BigDecimal conversion#7819
DarrenChangJR wants to merge 1 commit into
alibaba:mainfrom
DarrenChangJR:fix/big-decimal-double-conversion

Conversation

@DarrenChangJR

Copy link
Copy Markdown

What this PR does and why

TypeUtils.toBigDecimal(double) currently formats the binary value with the
JSON number writer and parses that output as a BigDecimal. The writer
guarantees that parsing the text as a double recovers the same bits, but it can
choose a different decimal from Double.toString.

For example, converting 0.00054797D returns
0.0005479699999999999 instead of the canonical 0.00054797 returned by
BigDecimal.valueOf, Fastjson1 TypeUtils.castToBigDecimal, and Fastjson2's
own internal Cast.toBigDecimal.

The same path formats NaN and infinities as null and then attempts to parse
that token as a decimal, causing NumberFormatException. Fastjson1 returns
null for those values.

This change:

  • uses BigDecimal.valueOf for finite doubles;
  • returns null for non-finite doubles and floats;
  • keeps the existing optimized finite-float path.

Tests

  • the reported value through TypeUtils, object conversion, JSONObject, and
    JSONArray;
  • 10,000 deterministic random double bit patterns against
    BigDecimal.valueOf;
  • NaN and both infinities for float and double;
  • clean full core suite: 7,977 tests, no failures or errors;
  • 2,181-probe compatibility matrix: 178 differences on 2.0.64, 174 on this
    branch.
中文说明

修改内容和原因

TypeUtils.toBigDecimal(double) 目前先使用 JSON 数字 writer 输出字符串,再
解析成 BigDecimal。该 writer 保证重新解析成 double 后二进制位一致,但不保证
采用 Double.toString 的规范十进制表示。

例如 0.00054797D 会得到 0.0005479699999999999,而
BigDecimal.valueOf、Fastjson1 TypeUtils.castToBigDecimal 以及 Fastjson2
内部的 Cast.toBigDecimal 都得到 0.00054797

同一路径还会先把 NaN / infinity 输出成 null,随后把 null 当十进制解析,
导致 NumberFormatException;Fastjson1 对这些值返回 null

本修改对有限 double 使用 BigDecimal.valueOf,对非有限 double/float 直接
返回 null,有限 float 则保留原有优化路径。

测试包含 10,000 个固定随机 double 位模式、JSONObject / JSONArray 公开
入口以及所有非有限值。clean 后完整 core 7,977 项测试均无失败;2,181 项兼容
矩阵的差异从 178 降至 174。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant