kotlin - Kotlin 使用 BigDecimal 与 Double 进行计算
问题描述
我有 2 个功能。一种使用BigInteger
和BigDecimal
。我想sin(z)
使用泰勒级数计算:
这是我的代码:
fun sinus(z: BigDecimal, upperBound: Int = 100): BigDecimal = calcSin(z, upperBound)
fun cosinus(z: BigDecimal, upperBound: Int = 100): BigDecimal = calcSin(z, upperBound, false)
fun calcSin(z: BigDecimal, upperBound: Int = 100, isSin: Boolean = true): BigDecimal {
var erg: BigDecimal = BigDecimal.ZERO
for (n in 0..upperBound) {
// val zaehler = (-1.0).pow(n).toBigDecimal() * z.pow(2 * n + (if (isSin) 1 else 0))
// val nenner = fac(2 * n + (if (isSin) 1 else 0)).toBigDecimal()
val zaehler = (-1.0).pow(n).toBigDecimal() * z.pow(2 * n + 1)
val nenner = fac(2 * n + 1).toBigDecimal()
erg += (zaehler / nenner)
}
return erg
}
fun calcSin(z: Double, upperBound: Int = 100): Double {
var res = 0.0
for (n in 0..upperBound) {
val zaehler = (-1.0).pow(n) * z.pow(2 * n + 1)
val nenner = fac(2 * n + 1, true)
res += (zaehler / nenner)
}
return res
}
fun fac(n: Int): BigInteger = if (n == 0 || n == 1) BigInteger.ONE else n.toBigInteger() * fac(n - 1)
fun fac(n: Int, dummy: Boolean): Double = if (n == 0 || n == 1) 1.0 else n.toDouble() * fac(n - 1, dummy)
根据谷歌的说法,Sin(1) 是
0.8414709848
然而,以下的输出是:
println("Sinus 1: ${sinus(1.0.toBigDecimal())}")
println("Sinus 1: ${sinus(1.0.toBigDecimal()).toDouble()}")
println("Sinus 1: ${sinus(1.0.toBigDecimal(), 1000)}")
println("Sinus 1: ${calcSin(1.0)}")
输出:
Sinus 1: 0.8414373208078281027995610599000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Sinus 1: 0.8414373208078281
Sinus 1: 0.8414373208078281027995610599000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Sinus 1: 0.8414709848078965
我错过了什么?为什么 Double-Variant 给出正确的值,而 BigDecimal 没有?即使有 1000 次迭代。注释掉的代码也用于计算 Cos,但想先找出问题,所以我让两个函数看起来一样
解决方案
在BigDecimal
变体中,尝试替换erg += (zaehler / nenner)
为erg += (zaehler.divide(nenner, 20, RoundingMode.HALF_EVEN))
我怀疑缩放除法结果的默认值(如此处所述https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/math/BigDecimal.html)不是你想要什么。
顺便说一句 - 我假设性能不是练习的一部分,否则你对阶乘的实现是一个容易实现的目标。
推荐阅读
- reactjs - Reactjs 视频播放器中的用户界面错误
- angular - 从 Angular 2 升级到 Angular 7,无法绑定 [x],因为它不是 [y] 的属性
- python - scipy curve_fit 不会改变初始猜测的参数
- javascript - 要求字符串输入时刻为某种格式
- android - Android Studio 无法找到 ADB,但我可以部署到我的设备
- bigcommerce - 使用 BigCommerce API 获取价格列表和名称
- javascript - WebRTC:通道、轨道和流与 RTP SSRC 和 RTP 会话之间的关系
- html - Aframe Sphere-Collider 碰撞触发功能
- vba - vba - 访问数字类型的字节
- javascript - 使用 SVG JS(ES6+)拖放与绘图线(路径)宽度链接的元素