-
Notifications
You must be signed in to change notification settings - Fork 42
BigDecimal Usage Overview
To create a BigDecimal you can parse a string in expanded or scientific notation
Scientific
val bigDecimal = BigDecimal.parseString("1.23E-6)")
println("BigDecimal: $bigDecimal")
----- Output -----
BigDecimal: 1.23E-6
Expanded
val bigDecimal = BigDecimal.parseString("0.00000123")
println("BigDecimal: $bigDecimal")
----- Output -----
BigDecimal: 1.23E-6
You can convert standard types to BigDecimal, i.e. Long
val bigDecimal = BigDecimal.fromLong(7111)
println("BigDecimal: $bigDecimal")
----- Output -----
BigDecimal: 7.111E+3
Or you can specify an exponent. when you do specify an exponent, input value (long, int, short, byte) is considered to be in scientific notation.
val bigDecimal = BigDecimal.fromLongWithExponent(1, (-5).toBigInteger())
println("BigDecimal: $bigDecimal")
println("BigDecimalExpanded: ${bigDecimal.toStringExpanded()}")
----- Output -----
BigDecimal: 1.0E-5
BigDecimalExpanded: 0.00001
For String
val bigDecimal = "12345678.123".toBigInteger
Or for Double
of Float
val bigDecimalFromFloat = 123.456f.toBigDecimal()
val bigDecimalFromDouble = 123.456.toBigDecimal()
By default toString() is returned in scientific output, but expanded output is also available
val bigDecimal = BigDecimal.parseString("123.456")
println("BigDecimal: ${bigDecimal.toStringExpanded()}")
bigDecimal.toStringExpanded() == "123.456"
----- Output -----
BigDecimal: 123.456
Standard arithmetic operations that are present:
- Addition
- Subtraction
- Multiplication
- Division
- Exponentiation
- Increase by one
- Decrease by one
- Absolute value
- Negate
- Signum
(Suspiciously missing is square root, both from BigInteger and BigDecimal, should be added soon™)
Operations are executed with existing significands and then rounded down afterwards. Decimal mode parameter controls the precision and rounding mode
This is a counterpart to the Java BigDecimal MathContext.
data class DecimalMode(val decimalPrecision : Long = 0, val roundingMode : RoundingMode = RoundingMode.NONE)
decimalPrecision
defines how many digits should significand have
roundingMode
defines rounding mode.
-
DecimalMode
supplied to the operation always overrides all otherDecimalModes
set inBigDecimal
s -
If a
DecimalMode
is set when creating aBigDecimal
that mode will be used for all operations. -
If two
BigDecimal
s have differentDecimalModes
with different RoundingModes anArithmeticException
will be thrown. If the modes are same, but the precision is different, larger precision will be used.
Precision 0 and roundingMode none attempt to provide infinite precisions. Exception is division, where default precision is
is the sum of precisions of operands (or 6, if the sum is below 6). If result of the operation cannot fit inside precision and RoundingMode is NONE, ArithmeticException
will be thrown.
Example from the tests:
fun readmeDivisionTest() {
assertFailsWith(ArithmeticException::class) {
val a = 1.toBigDecimal()
val b = 3.toBigDecimal()
val result = a/b
}
assertTrue {
val a = 1.toBigDecimal()
val b = 3.toBigDecimal()
val result = a.div(b, DecimalMode(20, RoundingMode.ROUND_HALF_AWAY_FROM_ZERO))
result.toString() == "3.3333333333333333333E-1"
}
}
Name | Description |
---|---|
FLOOR | Towards negative infinity |
CEILING | Towards positive infinity |
AWAY_FROM_ZERO | Away from zero |
TOWARDS_ZERO | Towards zero |
NONE | Infinite decimalPrecision, and beyond |
ROUND_HALF_AWAY_FROM_ZERO | Round towards nearest integer, using towards zero as tie breaker when significant digit being rounded is 5 |
ROUND_HALF_TOWARDS_ZERO | Round towards nearest integer, using away from zero as tie breaker when significant digit being rounded is 5 |
ROUND_HALF_CEILING | Round towards nearest integer, using towards infinity as tie breaker when significant digit being rounded is 5 |
ROUND_HALF_FLOOR | Round towards nearest integer, using towards negative infinity as tie breaker when significant digit being rounded is 5 |