如何实施斯特林&x27;在Kotlin中包含BigDecimal和BigInteger的s公式?
我想做一个阶乘程序。如果输入数低于250000,我使用尾部递归函数来查找该数的阶乘。 但是如果输入值超过250000,我会尝试使用斯特林公式()。我希望能够处理大整数和大小数,但每当我尝试计算250102时,我得到NaN(不是数字…错误)。你能帮帮我吗 以下是我在Kotlin中的代码:如何实施斯特林&x27;在Kotlin中包含BigDecimal和BigInteger的s公式?,kotlin,factorial,Kotlin,Factorial,我想做一个阶乘程序。如果输入数低于250000,我使用尾部递归函数来查找该数的阶乘。 但是如果输入值超过250000,我会尝试使用斯特林公式()。我希望能够处理大整数和大小数,但每当我尝试计算250102时,我得到NaN(不是数字…错误)。你能帮帮我吗 以下是我在Kotlin中的代码: import java.io.File import java.math.BigDecimal import java.math.BigInteger tailrec fun tail_recursion_fa
import java.io.File
import java.math.BigDecimal
import java.math.BigInteger
tailrec fun tail_recursion_factorial(n: BigInteger, factorialOfN: BigInteger = BigInteger.valueOf(2)): BigInteger {
return when(n){
BigInteger.ZERO -> BigInteger.ONE
BigInteger.ONE -> BigInteger.ONE
BigInteger.valueOf(2) -> factorialOfN
else -> tail_recursion_factorial(n.minus(BigInteger.ONE), n.times(factorialOfN))
}
}
// calculate approximate value of n!
// using Stirling's approximation:
fun Stirling_factorial(n: BigInteger): BigDecimal {
return BigDecimal.valueOf(Math.sqrt((2*n.toDouble()*1.0/3.0)*Math.PI))*BigDecimal.valueOf(Math.pow(n.toDouble(),n
.toDouble()))*BigDecimal.valueOf(Math.pow(Math.E,-1.0*n.toDouble()))
}
fun main(args: Array<String>){
print("n == ")
var n = readLine()
try {
when {
BigInteger(n) < BigInteger.ZERO -> println("Sorry bro! Can't do a factorial to a negative number.")
BigInteger(n) >= BigInteger.ZERO -> {
when{
BigInteger(n) <= BigInteger.valueOf(250000) -> {
File("factorial.txt").writeText("\"$n! is ${tail_recursion_factorial(BigInteger(n))}\"")
println("Check factorial.txt in the project directory!")
}
else -> {
println("Since your number is bigger than 250 000\nwe're calculating using the Stirling's formula wich is an approximation of the factorial.\n")
File("factorial.txt").writeText("The aproximation of $n! is\n${Stirling_factorial
(BigInteger(n))}")
println("Check factorial.txt in the project directory!")
}
}
}
}
}catch (e: NumberFormatException){
println("Sorry bro! Can't do that ...")
}
}
还有
fun Stirling_formula(n: BigDecimal) : BigDecimal {
val mathContext = MathContext(121)
return (BigDecimal.ONE + BigDecimal.ONE.divide(BigDecimal.valueOf(12).times(n),mathContext))
.times(BigDecimalMath.sqrt((n.times(BigDecimal.valueOf(2.0))).times(BigDecimalMath.pi(mathContext)), mathContext))
.times(BigDecimalMath.pow(n,n,mathContext))
.times(BigDecimalMath.pow(BigDecimalMath.e(mathContext),-n,mathContext))
谢谢你
PS:另外,我已经用更精确的近似值更新了公式:
对于如此大的计算,您需要一个合适的库。看一看
你需要一个合适的库来进行如此大的计算。看一看
为什么要在
Stirling\u阶乘函数中转换为双精度?这可能是你的错。我不得不说,因为Math.sqrt只适用于double。你为什么要在Stirling_factorial
函数中转换为double?这可能是你的错。我不得不这么做,因为Math.sqrt只适用于DoublesHanks兄弟!这对我有用。这不是世界上最好的精度,但很好,谢谢兄弟!这对我有用。不是世界上最好的精度,但它很好
fun Stirling_formula(n: BigDecimal) : BigDecimal {
val mathContext = MathContext(121)
return (BigDecimal.ONE + BigDecimal.ONE.divide(BigDecimal.valueOf(12).times(n),mathContext))
.times(BigDecimalMath.sqrt((n.times(BigDecimal.valueOf(2.0))).times(BigDecimalMath.pi(mathContext)), mathContext))
.times(BigDecimalMath.pow(n,n,mathContext))
.times(BigDecimalMath.pow(BigDecimalMath.e(mathContext),-n,mathContext))
val a = Math.pow(250102.0, 250102.0)
println(a) // >> Infinity
val b = BigDecimal(a) // Exception in thread "main" java.lang.NumberFormatException:
// Infinite or NaN