Repository navigation
Conversation
NumberUtils
sbrannen
left a comment
There was a problem hiding this comment.
Congratulations on submitting your first PR for the Spring Framework! 👍
The first commit looks good: detecting overflow for Double and Float values when converting to Long makes sense, as does rejecting NaN and infinite values for all integral types. Your range check handles the edge cases correctly, including the exclusive upper bound at 2^63. For readability, you might consider introducing constants for the bounds (-0x1p63 and 0x1p63) instead of using -(double) Long.MIN_VALUE.
However, the second commit introduces a regression for large values that are still within the long range. Float.toString() and Double.toString() return the shortest decimal string that represents the value, not its exact value, so digits are lost. For example:
0x1p40f(2^40) is converted to1099511600000instead of1099511627776.0x1p60(2^60) is converted to1152921504606847000instead of1152921504606846976.
Prior to this PR, both conversions were exact. In addition, converting NaN or an infinite value to BigInteger now fails with a rather cryptic NumberFormatException instead of the overflow exception used for the other integral types.
To address that in the second commit, please:
- Use
new BigDecimal(number.doubleValue()).toBigInteger(), which is exact for all finite values and consistent with the existing behavior for in-range values. - Raise the overflow exception for
NaNand infinite values before converting toBigInteger.
Regarding tests, please add assertions for:
- Large in-range values converted to
BigInteger(for example,0x1p40fand0x1p60), verifying that the results match theLongconversion. NaNand infinite values converted toBigInteger, verifying that the overflow exception is thrown.
Since this changes existing behavior (for example, NaN now throws instead of converting to 0), we'll consider it for 7.1 rather than backporting it.
Cheers,
Sam
Prior to this commit, NumberUtils.convertNumberToTargetClass() silently saturated Double and Float values outside the long range when converting to Long, for example 1e20 became Long.MAX_VALUE, while the same value raised an overflow exception for Integer. Likewise, NaN was silently converted to 0 for all integral types. This commit extends the long overflow check to Double and Float values, consistent with the existing check for BigInteger and BigDecimal values. Signed-off-by: 김성찬 <265934944+kimseongchan0914@users.noreply.github.com>
Prior to this commit, NumberUtils.convertNumberToTargetClass() converted Double and Float values to BigInteger through Number.longValue(), so values beyond the long range were silently truncated, for example 1e20 became Long.MAX_VALUE. This commit converts such values via their exact BigDecimal representation, analogous to the existing BigDecimal to BigInteger conversion, and raises an overflow exception for NaN and infinite values, consistent with the other integral target types. Signed-off-by: 김성찬 <265934944+kimseongchan0914@users.noreply.github.com>
105a1b2 to
afc046f
Compare
|
Thanks for the thorough review, @sbrannen! I've updated both commits:
|
Overview
NumberUtils.convertNumberToTargetClass()already checks for overflow when convertingBigIntegerandBigDecimalvalues to integral types (see gh-16060 and gh-18613), butDoubleandFloatvalues are passed toNumber.longValue()unchecked. Values outside the long range therefore saturate silently, andNaNbecomes0.The same behavior shows up through
DefaultConversionService:This PR contains two commits:
checkedLongValue()now rejectsDouble/Floatvalues outside[-2^63, 2^63), which includesNaNand infinite values. Integral targets,Longamong them, now raise the same overflow exception thatIntegerraises today.BigInteger: these values are converted viaBigDecimal, the same way the existingBigDecimaltoBigIntegerpath works, instead of being truncated to the long range.In-range values behave as before, for example
1.5still converts to1. SpEL operators and comparisons are not affected, because they handleDouble/Floatoperands before taking theBigIntegerpath.Related Issues