I'm working on some financial analysis software that will need to process large (ish) volumes of data. I'd like to use BigDecimal for the accuracy (some pricing info goes to four or five digits to the right of the decimal) but I was concerned about speed.
I wrote the following test app and it appears that BigDecimal can be 90 to 100 times slower than Doubles. I knew there would be a delta, but that's more than I was expecting. Here's a typical output after many trials.
BigDecimal took 17944 ms
Double took 181 ms
Am I missing something?
Here is the code. I tried to make it representative of real world. I created a constant where I could (pi) but also did some inline math of numbers that would vary from data row to data row - such as pi * BigDecimal(i) + BigDecimal(1). My point being that avoiding constructors can't be the only answer.
Fortunately, it appears Double has enough precision anyway since numbers will be typically in the format 00000.00000. Any hidden gotchas I should know about, though? Do people use Double for financial analysis software?
import java.math.BigDecimal
object Stopwatch {
inline fun elapse(f: () -> Unit):Long {
val start = System.currentTimeMillis()
f()
return System.currentTimeMillis() - start
}
}
fun tryBigDecimal() {
val arr: MutableList<BigDecimal> = arrayListOf()
for (i in 1..10000000) {
arr.add(BigDecimal(i))
}
val pi = BigDecimal(3.14159)
for (i in 0..arr.size - 1) {
arr[i] = arr[i] * pi / (pi * BigDecimal(i) + BigDecimal(1))
}
//arr.forEachIndexed { i, bigDecimal -> println("$i, ${bigDecimal.toString()}")}
}
fun tryDouble() {
val arr: MutableList<Double> = arrayListOf()
for (i in 1..10000000) {
arr.add(i.toDouble())
}
val pi = 3.14159
for (i in 0..arr.size - 1) {
arr[i] = arr[i] * pi / (pi * i + 1)
}
//arr.forEachIndexed { i, bigDecimal -> println("$i, ${bigDecimal.toString()}")}
}
fun main(args: Array<String>) {
val bigdecimalTime = Stopwatch.elapse(::tryBigDecimal)
println("BigDecimal took $bigdecimalTime ms")
val doubleTime = Stopwatch.elapse(::tryDouble)
println("Double took $doubleTime ms")
}