Skip to content

Commit ace11c0

Browse files
committed
Use MathContext in BigDecimal operations
1 parent a336708 commit ace11c0

File tree

2 files changed

+31
-7
lines changed

2 files changed

+31
-7
lines changed

src/library/scala/math/BigDecimal.scala

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -481,11 +481,11 @@ extends ScalaNumber with ScalaNumericConversions with Serializable with Ordered[
481481

482482
/** Addition of BigDecimals
483483
*/
484-
def + (that: BigDecimal): BigDecimal = new BigDecimal(this.bigDecimal add that.bigDecimal, mc)
484+
def + (that: BigDecimal): BigDecimal = new BigDecimal(this.bigDecimal.add(that.bigDecimal, mc), mc)
485485

486486
/** Subtraction of BigDecimals
487487
*/
488-
def - (that: BigDecimal): BigDecimal = new BigDecimal(this.bigDecimal subtract that.bigDecimal, mc)
488+
def - (that: BigDecimal): BigDecimal = new BigDecimal(this.bigDecimal.subtract(that.bigDecimal, mc), mc)
489489

490490
/** Multiplication of BigDecimals
491491
*/
@@ -499,14 +499,14 @@ extends ScalaNumber with ScalaNumericConversions with Serializable with Ordered[
499499
* divideToIntegralValue and the remainder. The computation is exact: no rounding is applied.
500500
*/
501501
def /% (that: BigDecimal): (BigDecimal, BigDecimal) =
502-
this.bigDecimal.divideAndRemainder(that.bigDecimal) match {
502+
this.bigDecimal.divideAndRemainder(that.bigDecimal, mc) match {
503503
case Array(q, r) => (new BigDecimal(q, mc), new BigDecimal(r, mc))
504504
}
505505

506506
/** Divide to Integral value.
507507
*/
508508
def quot (that: BigDecimal): BigDecimal =
509-
new BigDecimal(this.bigDecimal divideToIntegralValue that.bigDecimal, mc)
509+
new BigDecimal(this.bigDecimal.divideToIntegralValue(that.bigDecimal, mc), mc)
510510

511511
/** Returns the minimum of this and that, or this if the two are equal
512512
*/
@@ -524,19 +524,19 @@ extends ScalaNumber with ScalaNumericConversions with Serializable with Ordered[
524524

525525
/** Remainder after dividing this by that.
526526
*/
527-
def remainder (that: BigDecimal): BigDecimal = new BigDecimal(this.bigDecimal remainder that.bigDecimal, mc)
527+
def remainder (that: BigDecimal): BigDecimal = new BigDecimal(this.bigDecimal.remainder(that.bigDecimal, mc), mc)
528528

529529
/** Remainder after dividing this by that.
530530
*/
531-
def % (that: BigDecimal): BigDecimal = this remainder that
531+
def % (that: BigDecimal): BigDecimal = this.remainder(that)
532532

533533
/** Returns a BigDecimal whose value is this ** n.
534534
*/
535535
def pow (n: Int): BigDecimal = new BigDecimal(this.bigDecimal.pow(n, mc), mc)
536536

537537
/** Returns a BigDecimal whose value is the negation of this BigDecimal
538538
*/
539-
def unary_- : BigDecimal = new BigDecimal(this.bigDecimal.negate(), mc)
539+
def unary_- : BigDecimal = new BigDecimal(this.bigDecimal.negate(mc), mc)
540540

541541
/** Returns the absolute value of this BigDecimal
542542
*/

test/junit/scala/math/BigDecimalTest.scala

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import org.junit.runner.RunWith
44
import org.junit.runners.JUnit4
55
import org.junit.Test
66
import java.math.{BigDecimal => BD, MathContext => MC}
7+
import java.util.Formatter.BigDecimalLayoutForm
78

89
/* Tests various maps by making sure they all agree on the same answers. */
910
@RunWith(classOf[JUnit4])
@@ -259,6 +260,29 @@ class BigDecimalTest {
259260
testRounded()
260261
}
261262

263+
// Motivated by scala/bug#10882: Operators for BigDecimal don't use value of mc (MathContext)
264+
@Test
265+
def testUsesMathContextInOperators(): Unit = {
266+
def isAE[A](a: => A): Boolean = try { a; false } catch { case e: ArithmeticException => true }
267+
268+
val bd128 = BigDecimal("4.2e1000", MC.DECIMAL128)
269+
assert(bd128 + 10 == bd128)
270+
assert(bd128 - 10 == bd128)
271+
assert(bd128 + BigDecimal("1e100", MC.UNLIMITED) == bd128)
272+
assert(bd128 - BigDecimal("1e100", MC.UNLIMITED) == bd128)
273+
assert(bd128.quot(BigDecimal("1e100", MC.UNLIMITED)) == BigDecimal("4.2e900", MC.DECIMAL128))
274+
assert(isAE(bd128.quot(BigDecimal("1e100", MC.UNLIMITED) + 1)))
275+
assert(isAE(bd128 % (BigDecimal("1e100", MC.UNLIMITED) + 1)))
276+
assert(isAE(bd128 /% (BigDecimal("1e100", MC.UNLIMITED) + 1)))
277+
278+
val bdUnlimited = BigDecimal("4.2e1000", MC.UNLIMITED)
279+
assert(bdUnlimited + 10 > bdUnlimited)
280+
assert(bdUnlimited - 10 < bdUnlimited)
281+
assert(bdUnlimited + BigDecimal("1e100", MC.DECIMAL128) > bdUnlimited)
282+
assert(bdUnlimited - BigDecimal("1e100", MC.DECIMAL128) < bdUnlimited)
283+
assert(bdUnlimited.quot(BigDecimal("1e100", MC.DECIMAL128)) == BigDecimal("4.2e900", MC.UNLIMITED))
284+
}
285+
262286
@Test
263287
def testIsComparable(): Unit = {
264288
assert(BigDecimal(0.1).isInstanceOf[java.lang.Comparable[_]])

0 commit comments

Comments
 (0)