IgnatiusPang commented on PR #25741:
URL: https://github.com/apache/datafusion/pull/25741#issuecomment-5835247679
```markdown
### 1. SQL Reproducer (Extreme Precision Blowup)
```sql
-- High positive precision: factor overflows to Inf, producing Inf/Inf = NaN
SELECT round(1.5::float, 40) AS r;
-- Current: NaN
-- Expected: 1.5
SELECT trunc(42.5::float, 40) AS t;
-- Current: NaN
-- Expected: 42.5
-- High negative precision: factor underflows to 0.0, producing 0/0 = NaN
SELECT round(1.5::float, -50) AS r;
-- Current: NaN
-- Expected: 0.0
```
**Current Result (unpatched DataFusion):**
```text
+-----+
| r |
+-----+
| NaN |
+-----+
```
**Expected Result:**
- `round(1.5::float, 40)` should return `1.5` (a 32-bit float only has ~7
digits of precision; rounding beyond its precision is a no-op).
- `trunc(42.5::float, 40)` should return `42.5`.
- `round(1.5::float, -50)` should return `0.0`.
---
### 2. Root Cause
In `datafusion/functions/src/math/round.rs`:
```rust
fn round_factor<T: num_traits::Float>(decimal_places: i32) -> Result<T,
ArrowError> {
T::from(10_f64.powi(decimal_places)).ok_or_else(...)
}
fn round_float<T>(value: T, decimal_places: i32) -> Result<T, ArrowError> {
let factor = round_factor::<T>(decimal_places)?;
Ok((value * factor).round() / factor)
}
```
- `T::from(10_f64.powi(40))` on `f32` evaluates to `Some(f32::INFINITY)`.
- `(1.5 * inf).round() / inf = inf / inf = NaN`.
- `T::from(10_f64.powi(-50))` on `f32` evaluates to `Some(0.0)`.
- `(1.5 * 0.0).round() / 0.0 = 0.0 / 0.0 = NaN`.
### 3. Proposed Fix
Guard `round_factor` and `truncate_with_factor` against infinite or zero
factors: if the positive factor is infinite, return the original value; if the
factor underflows to zero, return zero.
```
--
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]