raghav-reglobe opened a new pull request, #69216:
URL: https://github.com/apache/doris/pull/69216

   ### What problem does this PR solve?
   
   Issue Number: close #69215
   
   Related PR: none
   
   Problem Summary:
   
   `CastToFloat::_from_decimalv3` computed `double(unscaled) / 
double(10^scale)`, which rounds twice once the unscaled
   integer exceeds 2^53: the integer-to-double conversion already rounds, and 
the division rounds again, so the result can
   be the double next to the correctly rounded one (`DECIMAL(38,12)` 
`29201.024999999998` → `29201.025`; 26.4 % of 20M
   generated 12-fraction-digit values differ). `CAST(CAST(x AS STRING) AS 
DOUBLE)` is exact, and a literal cast is exact
   because the FE folds it in BigDecimal, so the defect shows only on column 
data. DECIMAL-typed VARIANT elements take the
   same cast.
   
   The fix keeps the one-division path only when both operands are exact 
(|unscaled| < 2^53, scale ≤ 22, double target)
   and otherwise converts through the decimal's digits with 
`fast_float::from_chars` straight into the target type.
   `StringParser::string_to_float<float>` was not usable for the FLOAT target: 
it accumulates in double and narrows
   afterwards, which resolves an exact tie the wrong way (`DECIMAL(19,9)` 
`-9000000000.000000009` → FLOAT gave
   -8999999488 instead of -9000000512).
   
   Cost on 20M values: the fast path is unchanged; the digit path adds roughly 
40–60 ns per value, about the cost of the
   text-route workaround.
   
   ### Release note
   
   Fix `CAST(DECIMAL AS DOUBLE/FLOAT)` returning the neighbouring 
floating-point value for decimals whose unscaled value
   exceeds 2^53; the conversion is now correctly rounded.
   
   ### Check List (For Author)
   
   - Test
       - [x] Unit Test — `FunctionCastToFloatTest`: the parametrized 
`test_from_decimal` expectations now follow the
         decimal's digits (`strtod` / `strtof`) instead of the two-rounding 
formula, and a witness test pins wide
         `DECIMAL(38,12)` values.
       - [x] Manual test — the 20M-row `numbers()` query from the issue: 
5,273,258 mismatches before, 0 after.
   
   - Behavior changed:
       - [x] Yes. `CAST(decimal AS DOUBLE/FLOAT)` returns the correctly rounded 
value where it previously returned the
         adjacent one (only for unscaled values beyond 2^53).
   
   - Does this need documentation?
       - [x] No.
   


-- 
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]

Reply via email to