Giter VIP home page Giter VIP logo

kotlin-big-math's Introduction

Build Status Maven Central

kotlin-big-math

Kotlin library for BigDecimal math functions (pow, sqrt, log, sin, ...) using arbitrary precision.

Introduction

This library depends on the big-math library and provides additional Kotlin features to do calculations with arbitrary precision.

It provides two different approaches to do the calculations

  • BigDecimal + DefaultBigDecimalMath : recommended approach
  • BigFloat : experimental approach

The big-math library provides advanced math functions (pow, sqrt, log, sin, ...).

The kotlin-big-math library enhances the big-math library with the kotlin specific operators and infix methods. Additionally it solves several of the problems that the standard kotlib library has when using BigDecimal.

BigDecimal + DefaultBigDecimalMath

By using the following imports you can use the standard BigDecimal class and the mathematical functions in DefaultBigDecimalMath in a simple but powerful manner:

import java.math.BigDecimal
import java.math.BigDecimal.*
import ch.obermuhlner.math.big.DefaultBigDecimalMath.*
import ch.obermuhlner.math.big.kotlin.bigdecimal.*

BigDecimal Operators

  • + operator

  • - operator

  • * operator

  • / operator

  • % operator

  • ++ operator

  • -- operator

  • pow infix method

  • root infix method

  • valueOf(Int) method (equivalent to BigDecimal(Int) constructor)

Using BigDecimal + DefaultBigDecimalMath in Kotlin

The usage of DefaultBigDecimalMath follows the same rules as described in the big-math library.

To specify a temporary local MathContext you can either use createLocalMathContext() method with use:

createLocalMathContext(10).use {
    // do some calculations using DefaultBigDecimalMath
}

Alternatively you can use the withLocalMathContext() method

withLocalMathContext(10) {
    // do some calculations using DefaultBigDecimalMath
}

Full example:

import java.math.BigDecimal
import java.math.BigDecimal.*
import ch.obermuhlner.math.big.DefaultBigDecimalMath.*
import ch.obermuhlner.math.big.kotlin.bigdecimal.*

fun main(args: Array<String>) {
	simpleExample()
	createLocalMathContextExample()
	withLocalMathContextExample()
	piChudnovskyExample()
}

fun simpleExample() {
	val v1 = valueOf(2) / 3

	println(v1)
}

fun createLocalMathContextExample() {
	println("Pi[default]: " + pi())

	createLocalMathContext(5).use {
		println("Pi[5]: " + pi())

		createLocalMathContext(10).use {
			println("Pi[10]: " + pi())
		}

		println("Pi[5]: " + pi())
	}

	println("Pi[default]: " + pi())
}

fun withLocalMathContextExample() {
	println("Pi[default]: " + pi())

	withLocalMathContext(5) {
		println("Pi[5]: " + pi())

		withLocalMathContext(10) {
			println("Pi[10]: " + pi())
		}

		println("Pi[5]: " + pi())
	}

	println("Pi[default]: " + pi())
}

fun piChudnovskyExample() {
	withLocalMathContext(100) {
		println(piChudnovsky())
	}
}

fun piChudnovsky() : BigDecimal {
	val valueDivisor = (valueOf(640320) pow 3) / 24

	var sumA = valueOf(1)
	var sumB = valueOf(0)

	var a = valueOf(1)
	var dividendTerm1 = valueOf(5) // -(6*k - 5)
	var dividendTerm2 = valueOf(-1) // 2*k - 1
	var dividendTerm3 = valueOf(-1) // 6*k - 1

	val precision = currentMathContext().precision
	val iterationCount = (precision+13) / 14 + 1
	for (k in 1 .. iterationCount) {
		dividendTerm1 += -6
		dividendTerm2 += 2
		dividendTerm3 += 6
		
		val dividend = dividendTerm1 * dividendTerm2 * dividendTerm3
		val divisor = (valueOf(k) pow 3) * valueDivisor
		a *= dividend / divisor
		val b = a * k
		
		sumA += a
		sumB += b
	}
	
	val factor = sqrt(valueOf(10005)) * 426880;
	val pi = factor / (sumA * 13591409 + sumB * 545140134);
	
	return pi;
}

This produces the following output:

0.6666666666666666666666666666666667
Pi[default]: 3.141592653589793238462643383279503
Pi[5]: 3.1416
Pi[10]: 3.141592654
Pi[5]: 3.1416
Pi[default]: 3.141592653589793238462643383279503
Pi[default]: 3.141592653589793238462643383279503
Pi[5]: 3.1416
Pi[10]: 3.141592654
Pi[5]: 3.1416
Pi[default]: 3.141592653589793238462643383279503
3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117069

BigFloat

The BigFloat class is a wrapper around BigDecimal which simplifies the consistent usage of the MathContext and provides a simpler API for calculations.

This is an experimental implementation. Your mileage may vary.

Use the following imports:

import ch.obermuhlner.math.big.BigFloat
import ch.obermuhlner.math.big.BigFloat.*
import ch.obermuhlner.math.big.kotlin.bigfloat.*

BigFloat Operators

  • + operator

  • - operator

  • * operator

  • / operator

  • ++ operator

  • -- operator

  • pow infix method

  • root infix method

Using BigFloat in Kotlin

The usage of BigFloat follows the same rules as described in the big-math library.

import ch.obermuhlner.math.big.BigFloat
import ch.obermuhlner.math.big.BigFloat.*
import ch.obermuhlner.math.big.kotlin.bigfloat.*

fun main(args: Array<String>) {
	simpleExample()
	piExample()
}

fun simpleExample() {
	val context = context(100)
	val v1 = context.valueOf(2) / 3

	println(v1)
}

fun piExample() {
	println(piChudnovsky(100))
}

fun piChudnovsky(precision: Int) : BigFloat {
	val context = context(precision + 10)
	
	val valueDivisor = (context.valueOf(640320) pow 3) / 24

	var sumA = context.valueOf(1)
	var sumB = context.valueOf(0)

	var a = context.valueOf(1)
	var dividendTerm1 = context.valueOf(5) // -(6*k - 5)
	var dividendTerm2 = context.valueOf(-1) // 2*k - 1
	var dividendTerm3 = context.valueOf(-1) // 6*k - 1
	
	val iterationCount = (context.getPrecision()+13) / 14 + 1
	for (k in 1 .. iterationCount) {
		dividendTerm1 += -6
		dividendTerm2 += 2
		dividendTerm3 += 6
		
		val dividend = dividendTerm1 * dividendTerm2 * dividendTerm3
		val divisor = (context.valueOf(k) pow 3) * valueDivisor
		a *= dividend / divisor
		val b = a * k
		
		sumA += a
		sumB += b
	}
	
	val factor = sqrt(context.valueOf(10005)) * 426880;
	val pi = factor / (sumA * 13591409 + sumB * 545140134);
	
	return context(precision).valueOf(pi);
}

This produces the following output:

0.6666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667
3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068

Comparison with standard kotlin library

The standard kotlin library already provides operators for BigDecimal but there are several problems with this solution.

Standard Kotlin: Precision problem in division

The precision of the standard operators is determined from the arguments. In the case of the division this can lead to unexpected results!

    // Code example with standard kotlin library (without kotlin-big-math)
    
    val v = valueOf(2) / valueOf(3)
    println(v) // prints: 1 !!!

This problem is solved in kotlin-big-math because the precision is specified outside the function call.

    // Code example with kotlin-big-math

    val v = valueOf(2) / valueOf(3)
    println(v) // prints: 0.6666666666666666666666666666666667

Standard Kotlin: Missing valueOf(Int) function

The Java BigDecimal class has two overloaded valueOf() functions for the types Double and Long but not for Int.

    // Code example with standard kotlin library (without kotlin-big-math)
    
    val n = 2
    val v0 = valueOf(n) // Compile Error!

This code does not compile but gives the following error:

Compile Error: None of the following functions can be called with the arguments supplied.
   valueOf(Double) defined in java.math.BigDecimal
   valueOf(Long) defined in java.math.BigDecimal

This problem is solved in kotlin-big-math by providing a fun valueOf(Int): BigDecimal.

    // Code example with kotlin-big-math

    val n = 2
    val v = valueOf(n)

Standard Kotlin: Missing overloaded operators for Int, Double, Long

The standard kotlin library does not provide overloaded operators for mixing Int, Double, Long with BigDecimal. This leads to unnecessary clutter:

    // Code example with standard kotlin library (without kotlin-big-math)
    
    val v1 = valueOf(2)
    val v2 = v1 * valueOf(3)
    val v3 = valueOf(4) * v1

This problem is solved in kotlin-big-math by providing a overloaded operators where one argument is Int, Double or Long.

    // Code example with kotlin-big-math

    val v1 = valueOf(2)
    val v2 = v1 * 3
    val v3 = 4.0 * v1

Using kotlin-big-math in your projects

To use the kotlin library you can either download the newest version of the .jar file from the published releases on Github or use the following dependency to Maven Central in your build script (please verify the version number to be the newest release):

Use kotlin-big-math in Maven Build

<dependency>
    <groupId>ch.obermuhlner</groupId>
    <artifactId>kotlin-big-math</artifactId>
    <version>2.3.0</version>
</dependency>

Use kotlin-big-math in Gradle Build

repositories {
  mavenCentral()
}

dependencies {
  compile 'ch.obermuhlner:kotlin-big-math:2.3.0'
}

kotlin-big-math's People

Contributors

breandan avatar eobermuhlner avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

kotlin-big-math's Issues

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.