Skip to content

Conversation

@xuwei-k
Copy link
Contributor

@xuwei-k xuwei-k commented Sep 20, 2018

@scala-jenkins scala-jenkins added this to the 2.13.0-RC1 milestone Sep 20, 2018
@szeiger
Copy link
Contributor

szeiger commented Sep 21, 2018

I'm pretty sure this is the wrong way to (try to) fix the problem but I'm not sure what they right way would be. The non-terminating NumericRangeIterator is a result of the underlying problem, not the cause. The NumericRange itself is still just as broken and produces incorrect results:

scala> (BigDecimal(1) to BigDecimal(s"1.${"0" * 32}1") by BigDecimal(s"0.${"0" * 33}1"))
res0: scala.collection.immutable.NumericRange.Inclusive[scala.math.BigDecimal] = NumericRange 1 to 1.000000000000000000000000000000001 by 1E-34

scala> res0(0)
res1: scala.math.BigDecimal = 1.000000000000000000000000000000000

scala> res0(1)
res2: scala.math.BigDecimal = 1.000000000000000000000000000000000

scala> res0(2)
res3: scala.math.BigDecimal = 1.000000000000000000000000000000000

The only reasonable fix I can think of is to extend the precision as necessary instead of holding on to a specific MathContext, i.e. do what Java's BigDecimal does by default. Since NumericRange has no control over the operator semantics (nor should it) the change has to go into BigDecimal, which means reverting #6884. Is there a reason why some operators originally propagated the MathContext but others did not? I don't know. Is propagating the MathContext a good idea at all? Maybe Java got it right in the first place.

@Ichoran
Copy link
Contributor

Ichoran commented Sep 21, 2018

BigDecimal should be able to handle the math, if the precision is set properly to begin with. If BigDecimal propagates the correct MathContext, everything should be fine. The trick is just to set the precision based on the string input, which should happen on all creations of BigDecimal, most likely.

@szeiger
Copy link
Contributor

szeiger commented Oct 9, 2018

@Ichoran That doesn't work. The precision is set correctly based on the string input but ever since #6884 all BigDecimal operations use the MathContext from the LHS, i.e. the start value of the range. If the step size is much smaller then the start value the start value's precision won't be sufficient. To ensure a correct result you need to extend the precision to cover both operands (which was the original behavior before #6884).

We could switch the operands to reduce the scope of this problem (based on the assumption that the start value will not usually need more precision than the step) but it will still be incorrect in some cases.

@SethTisue SethTisue added the WIP label Nov 6, 2018
@SethTisue
Copy link
Member

marking as WIP but leaving open since there are plausible paths forward but it's not mergeable as-is

@SethTisue SethTisue added the library:collections PRs involving changes to the standard collection library label Nov 8, 2018
@SethTisue
Copy link
Member

/cc @gmethvin, since reverting #6884 is under consideration

@szeiger
Copy link
Contributor

szeiger commented Dec 11, 2018

I took a look at the history of BigDecimal. Not propagating the math context for some operations was not an oversight but a deliberate change introduced in 3a1332c to avoid a similar problem. I'll open a PR to revert #6884.

@szeiger
Copy link
Contributor

szeiger commented Dec 11, 2018

Closing in favor of #7516

@szeiger szeiger closed this Dec 11, 2018
@SethTisue SethTisue removed this from the 2.13.0-RC1 milestone Jan 2, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

library:collections PRs involving changes to the standard collection library

Projects

None yet

Development

Successfully merging this pull request may close these issues.

'(BigDecimal(1) to BigDecimal(s"1.${"0" * 32}1") by BigDecimal(s"0.${"0" * 33}1")).toList' cause infinite loop in Scala 2.13.0-M5

5 participants