我正在开发一些需要处理大量数据的财务分析软件。我想使用 BigDecimal 来提高准确性(某些定价信息会精确到小数点右侧四位或五位数字),但我担心速度。
我编写了以下测试应用程序,看来 BigDecimal 可能比 Doubles 慢 90 到 100 倍。我知道会有三角洲,但这超出了我的预期。这是经过多次试验后的典型输出。
BigDecimal took 17944 ms
Double took 181 ms
我错过了什么吗?
这是代码。我试图让它代表现实世界。我创建了一个常量,我可以在其中 (pi) 进行一些内联数学运算,这些数字因数据行而异,例如 pi * BigDecimal(i) + BigDecimal(1)。我的观点是,避免构造函数并不是唯一的答案。
幸运的是,Double 似乎具有足够的精度,因为数字通常采用 00000.00000 格式。不过,有什么我应该知道的隐藏问题吗?人们使用 Double 进行财务分析软件吗?
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")
}
最佳答案
您可以尝试Moneta ,JSR 354 引用实现 (JavaMoney RI)。它有一个 FastMoney
实现:
FastMoney
represents numeric representation that was optimized for speed. It represents a monetary amount only as a integral number of typelong
, hereby using a number scale of 100'000 (10^5).
例如
operator fun MonetaryAmount.times(multiplicand: Double): MonetaryAmount {
return multiply(multiplicand)
}
operator fun MonetaryAmount.div(divisor: Double): MonetaryAmount {
return divide(divisor)
}
fun tryFastMoney() {
val currency = Monetary.getCurrency("USD")
val arr: MutableList<MonetaryAmount> = arrayListOf()
for (i in 1..10000000) {
arr.add(FastMoney.of(i, currency))
}
val pi = 3.14159
for (i in 0..arr.size - 1) {
arr[i] = arr[i] * pi / (pi * i + 1)
}
}
fun main(args: Array<String>) {
val fastMoneyTime = Stopwatch.elapse(::tryFastMoney)
println("FastMoney took $fastMoneyTime ms")
val doubleTime = Stopwatch.elapse(::tryDouble)
println("Double took $doubleTime ms")
}
FastMoney took 7040 ms
Double took 4319 ms
关于java - 有没有办法让 BigDecimal 比我这里更快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39921191/