Use big-math¶
Package org.gciatto.kt.math.big is a port of big-math (by Eric
Obermühlner, MIT license): the functions java.math lacks, at any precision, on every platform. big-math's
BigDecimalMath static methods are extension functions on BigDecimal (x.log(mc)), or top-level functions when
they have no BigDecimal argument (pi(mc), factorial(n)) and for atan2(y, x, mc), and take a MathContext for
the precision of the result. Java sees them as the static methods of the BigDecimalMath class, as in big-math;
JavaScript, as functions taking the BigDecimal as their first argument.
It is part of Kt-Math's single artifact: see Add Kt-Math as a dependency.
Constants¶
assertDigits("3.1415926535897932384626433832795028841971693993751", pi(mc))
assertDigits("2.7182818284590452353602874713526624977572470937000", e(mc))
assertDigits("3.14159", pi(MathContext(6)))
Roots, powers and logarithms¶
assertDigits("1.4142135623730950488016887242096980785696718753769", dec("2").sqrt(mc))
assertDigits("1.2599210498948731647672106072782283505702514647015", dec("2").root(dec("3"), mc))
assertDigits("0.69314718055994530941723212145817656807550013436026", dec("2").log(mc))
assertDigits("3", dec("1000").log10(mc))
assertDigits("1E+1", dec("1024").log2(mc))
assertDigits("1024", dec("2").pow(dec("10"), mc))
assertDigits(
"1.4142135623730950488016887242096980785696718753769",
dec("2").pow(dec("0.5"), mc),
)
Trigonometric and hyperbolic functions¶
assertDigits("0.84147098480789650665250232163029899962256306079837", dec("1").sin(mc))
assertDigits("0.54030230586813971740093660744297660373231042061792", dec("1").cos(mc))
assertDigits("0.78539816339744830961566084581987572104929234984378", dec("1").atan(mc))
assertDigits("1.1752011936438014568823818505956008151557179813341", dec("1").sinh(mc))
assertFailsWith<ArithmeticException> { dec("1.5").asin(mc) }
Factorial, gamma, Bernoulli numbers¶
assertDigits("2432902008176640000", factorial(20))
assertDigits("0.88622692545275801364908374167057259139877472806119", dec("1.5").gamma(mc))
assertEquals("1/6", BigRational.bernoulli(2).reduce().toRationalString())
assertEquals("-1/30", BigRational.bernoulli(4).reduce().toRationalString())
assertFailsWith<UnsupportedOperationException> { dec("1").exp(MathContext.UNLIMITED) }
Complex numbers¶
BigComplex ports big-math's BigComplex and BigComplexMath: arithmetic, with operators when exact, and the
functions above as members (z.log(mc), z.pow(w, mc), z.sqrt(mc), ...).
val mc = MathContext(30)
val i = BigComplex.I
val z = BigComplex.valueOf(3.0, 4.0)
assertEquals(BigComplex.valueOf(-1.0), i * i)
assertDigits("5.0", z.abs(mc))
assertEquals("(2.20 - 0.40 i)", z.div(BigComplex.valueOf(1.0, 2.0), mc).toString())
assertEquals("(-7.00 + 24.00 i)", z.pow(2, mc).toString())
assertEquals("(0 + 3.14159265358979323846264338328 i)", BigComplex.valueOf(-1.0).log(mc).toString())
assertEquals("(0E-33 + 1.17520119364380145688238185060 i)", i.sin(mc).toString())
// the cube roots of 8: 2 (the principal one), -1 + 1.732... i, -1 - 1.732... i
assertEquals(BigComplex.valueOf(2.0), BigComplex.valueOf(8.0).root(3, 0, mc))
assertEquals(
"(-1.00000000000000000000000000000 + 1.73205080756887729352744634151 i)",
BigComplex.valueOf(8.0).root(3, 1, mc).toString(),
)
Ranges¶
big-math's BigDecimalStream is range and rangeClosed, returning Kotlin sequences, plus step on a..b and
a..<b (computed with MathContext.DECIMAL128).
val quarter = dec("0.25")
assertEquals("0, 0.25, 0.50, 0.75, 1.00", (dec("0")..dec("1") step quarter).joinToString())
assertEquals("0, 0.25, 0.50, 0.75", (dec("0")..<dec("1") step quarter).joinToString())
assertEquals("1, 0.75, 0.50", (dec("1")..<dec("0.25") step -quarter).toList().joinToString())
assertEquals("1, 1.3333", rangeClosed(dec("1"), dec("1.5"), dec("0.3333"), mc).joinToString())
big-math's BigFloat (a BigDecimal bundled with its MathContext) and DefaultBigDecimalMath (thread-local default
MathContexts) are not ported: BigDecimal and an explicit MathContext do the same.
The results are compared with big-math itself in Kt-Math's JVM tests, digit by digit.