java - 有没有办法让 BigDecimal 比我这里更快?

标签 java kotlin bigdecimal

我正在开发一些需要处理大量数据的财务分析软件。我想使用 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 type long, 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/

相关文章:

java - 我的 Android 应用程序遇到问题

java - 使用 HALF_UP 舍入到最接近的值

java - 在 Android 的 View 中创建透明圆形切口

Java 调试 servlet

kotlin - 热衷于通过 Kotlin Reflection API 获取无参数构造函数?

spring-boot - Kotlin Spring Boot 注解处理 "Cannot Resolve Configuration Processing"

java - 关于大数

java - Bigdecimal 中的减法问题

java - 在 log(n) 时间内获取排序数组中落在特定范围内的元素数量

java - NDK : Pass text field value to c++ string