Reputation: 67
I have a BigDecimals that's always have 30 digits after the decimal points.
And I want to multiply them with Double and get a BigDecimal with 30 digits after decimal point.
For exemple I have:
val double = 4.0
val bd = 0.111111111111111111111111111111
def multiply(d : Double, bd : BigDecimal, scale: Int) = {
BigDecimal.valueOf(d).setScale(scale).*(bd)
}
// multiply(double,bd,30) => 0.4444444444444444000000000000000000
I expected to get 0.444444444444444444444444444444
(30 times 4 after the point)
What is wrong with my method?
Upvotes: 0
Views: 842
Reputation: 20551
Your bd
isn't a BigDecimal
, it's a Double
:
scala> val bd = 0.111111111111111111111111111111
val bd: Double = 0.1111111111111111
It gets implicitly converted to a BigDecimal
(after losing precision from Double
) when you call multiply
.
To create the BigDecimal
, you seek, it's probably best to parse a string representation:
val bd = BigDecimal("0.111111111111111111111111111111")
// bd.scale is 30
It's also probably a good idea to explicitly set the scale again in multiply
after the multiplication, as it's possible for multiplying two numbers, even with the same scale, to have greater scale than either number.
def multiply(d: Double, bd: BigDecimal, scale:Int): BigDecimal =
(BigDecimal.valueOf(d).setScale(scale) * bd).setScale(scale)
Upvotes: 3
Reputation: 2821
Scala's BigDecimal is similar to Java's BigDecimal.
*
method on the left one), you get a new BigDecimal whose scale is the sum of the scale of its operands (inputs).bd
is not a BigDecimal, so its name is misleading. It is actually a double. In order to instantiate a BigDecimal, you should use a constructor, for example: BigDecimal("0.111111111111111111111111111111")
.val bd = BigDecimal("0.111111111111111111111111111111")
val double = 4.0
// There is no need to call `setScale` on `d` due to the first point noted above. Set it after multiplying:
def multiply(d : Double, bd : BigDecimal, scale: Int) =
(BigDecimal.valueOf(d) * bd).setScale(scale)
val result = multiply(double, bd, 30)
println(result)
println(result.scale)
Result:
0.444444444444444444444444444444
30
Upvotes: 3