[
https://issues.apache.org/jira/browse/CONFIGURATION-766?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16961984#comment-16961984
]
Alex Herbert commented on CONFIGURATION-766:
--------------------------------------------
So there is an issue that conversion using Double.toString(double) always puts
a decimal point in the output string. This results in BigDecimal having a
different scale when constructed using 'BigDecimal.valueOf(double)' rather than
'new BigDecimal(double)'. This is even documented in the BigDecimal source code
as a problem when using BigDecimal.valueOf(0.0) that it cannot return
BigDecimal.ZERO.
So in the following you test the double has a fractional part:
{code:java}
public static BigDecimal toBigDecimal(final Object value) throws
ConversionException
{
final Number n = toNumber(value, BigDecimal.class);
if (n instanceof BigDecimal)
{
return (BigDecimal) n;
}
// Avoid 'new BigDecimal(double)' for non-integer valued doubles due to
floating-point
// conversion errors.
// The BigDecimal constructor is used when a mathematical integer as the
scale will
// be set appropriately without a forced decimal point.
// Note: Math.rint(double) works for values outside the range of a long but
will ignore
// non-finite numbers. These will result in an exception from BigDecimal
which cannot
// represent them.
final double d = n.doubleValue();
return Math.rint(d) == d ? new BigDecimal(d) : BigDecimal.valueOf(d);
}
{code}
This may not be the best solution but would fix the regression error. It may
introduce a 'doubles should not be compared using equals' alert from sonar
which we can ignore; this is exactly what we intend.
Note that Math.rint will return the same value if the number is NaN or infinite
and usually this should be tested for using Double.isFinite(double). However
these have no meaning in BigDecimal and result in a NumberFormatException being
thrown. This can be tested:
{code:java}
@Test(expected = NumberFormatException.class)
public void testToBigDecimalWithInfinity() {
PropertyConverter.toBigDecimal(Double.POSITIVE_INFINITY);
}
{code}
The alternative is to update the other failing test as you state to test
against "42.0".
[~ggregory] What do you think?
# Use the simple fix to always use BigDecimal.valueOf(double) and update the
other failing test.
# Use a detection of the type of double to be represented and avoid the
regression failure.
> BigDecimal(double) should not be used
> -------------------------------------
>
> Key: CONFIGURATION-766
> URL: https://issues.apache.org/jira/browse/CONFIGURATION-766
> Project: Commons Configuration
> Issue Type: Bug
> Environment: A single occurrence in file PropertyConverter.java, line
> 393:
> {code:java}
> return new BigDecimal(n.doubleValue());
> {code}
> Reporter: Haris Adzemovic
> Priority: Minor
>
> Static analysis with SonarQube shows a violation of ruleĀ
> [S2111|[https://rules.sonarsource.com/java/type/Bug/RSPEC-2111]] - a
> dangerous use of the BigDecimal constructor.
> Fixed by using BigDecimal.valueOf(param) instead.
--
This message was sent by Atlassian Jira
(v8.3.4#803005)