-
Notifications
You must be signed in to change notification settings - Fork 970
Fix panic on lossy decimal to float casting: round to saturation for overflows #7887
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
… conversion process and error handling
… detailed context in error messages, such as failing element index and input value.
Is it possible that the issue is that the float conversion is fallible, I wouldn't have expected the conversion to be fallible? Can we fix this? Changing to try_unary will significantly regress performance and may be the wrong fix? |
… include detailed context in error messages, such as failing element index and input value." This reverts commit cf9268d.
…d Float64 conversions
Thanks @tustvold for the quick feedback ✅ What we’re doing now (safe, slow):
🛠 Alternative approaches (fast, risky or complex):
|
I would expect us to follow standard floating point overflow behaviour. Ultimately if you're opting for floating point numbers you are opting for this behaviour. Floating point in general is not appropriate for financial data as it is lossy by design. |
…ion failures" This reverts commit f25ec6b3ba8561f8a66b276d9d7869f8636ce48c.
…f error on overflow - Changed decimal-to-float casts to use lossy conversion consistent with IEEE semantics, saturating to ±INFINITY instead of returning an error on overflow or out-of-range values. - Updated `cast_decimal_to_float` to use infallible conversion function signature. - Added `decimal256_to_f64` helper for Decimal256 to f64 conversion with saturation. - Adjusted casting logic in `cast_with_options` accordingly. - Removed tests that expected errors on decimal-to-float overflow since now conversion saturates. - Clarified documentation to specify that decimal to float casts are lossy and saturate on overflow.
@@ -8660,6 +8673,16 @@ mod tests { | |||
"did not find expected error '{expected_error}' in actual error '{err}'" | |||
); | |||
} | |||
#[test] | |||
fn test_cast_decimal256_to_f64_overflow() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this need to cover negative infinity?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch.
I amended the test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you also please either add or ensure there is an existing test for casting Decimal128
(i128::MIN
and i128::MAX
to f64
)
… casting Decimal256 to Float64
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -891,7 +893,7 @@ pub fn cast_with_options( | |||
scale, | |||
from_type, | |||
to_type, | |||
|x: i256| x.to_f64().unwrap(), | |||
|x: i256| decimal256_to_f64(x), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to do something similar for Decimal128 above?
@@ -1993,6 +1995,17 @@ where | |||
} | |||
} | |||
|
|||
/// Convert a [`i256`] to `f64` saturating to infinity on overflow. | |||
fn decimal256_to_f64(v: i256) -> f64 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Saturating to INF seems a better solution than panic'ing
@@ -8660,6 +8673,16 @@ mod tests { | |||
"did not find expected error '{expected_error}' in actual error '{err}'" | |||
); | |||
} | |||
#[test] | |||
fn test_cast_decimal256_to_f64_overflow() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you also please either add or ensure there is an existing test for casting Decimal128
(i128::MIN
and i128::MAX
to f64
)
Which issue does this PR close?
Closes #7886.
Rationale for this change
Casting large
Decimal256
values toFloat64
can exceed the representable range of floating point numbers. Previously, this could result in a panic due to unwrapping a failed conversion.This PR introduces a safe conversion that saturates overflowing values to
INFINITY
or-INFINITY
, following standard floating point semantics. This ensures stable, predictable behavior without runtime crashes.What changes are included in this PR?
decimal256_to_f64
that convertsi256
tof64
, returningINFINITY
or-INFINITY
when the value is out of range.Decimal256
→Float64
to use the new safe conversion.test_cast_decimal256_to_f64_overflow
to validate overflow behavior.Are there any user-facing changes?
Yes.
Decimal256
values that exceed thef64
range, users now receiveINFINITY
or-INFINITY
instead of a panic.