如何在Kotlin中使用BigDecimal和BigInteger实现斯特林公式?

我正在尝试做一个阶乘程序。 如果输入数字低于250 000,我使用尾递归函数来查找该数字的阶乘。 但是,如果输入数字超过250 000的价值,我尝试使用斯特林公式( 在这里输入图像描述 )。 我想能够使用BigIntegers和BigDecimals,但是每当我尝试计算250 102时,我都会得到NaN(不是数字…错误)。 你能帮我么?

这是我在Kotlin的代码:

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 ...") } } 

编辑:问题解决了

 import ch.obermuhlner.math.big.BigDecimalMath import java.io.File import java.math.BigDecimal import java.math.MathContext 

和….

 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)) 

非常感谢Alexander Romanov

PS:我也更新了一个稍微更准确的近似公式: 在这里输入图像描述

你需要一个适当的库来处理这么大的计算。 看看kotlin-big-math 。

 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